Java并发编程入门(十四)CountDownLatch应用场景

一、应用场景

现实生活做中有很多这样的场景:做F前需要等待A,B,C,D,E完成,A,B,C,D,E可以并发完成,没有特定顺序,例如:周末在家里吃饭,有3件事情要做,爸爸做饭,妈妈做菜,儿子收拾餐桌,摆放碗筷。可以看到这个场景的特征为:

1.在吃饭前有N件事情要做,每件事情都做完后才能吃饭,待处理的事情为N,每做完一件待处理事情就减少1,当待处理事情为0时,就可以吃饭了。

2.每件事情可以并行处理,没有先后顺序,因而提高了效率。

围绕吃饭,整个过程如下:

在应用程序中处理并行操作时和上述场景类似,碰到这种场景时可以通过java并发工具CountDownLatch来实现。

二、Show me code

代码类结构如下:

I、EatingActivity.java

class EatingActivity implements Runnable {

    private CountDownLatch countDownLatch;

    public EatingActivity(CountDownLatch countDownLatch) {
        this.countDownLatch = countDownLatch;
    }

    public void run() {
        try {
            //等待吃饭
            System.out.println("Waiting for dinner...");
            this.countDownLatch.await();

            //所有事情做完后,await被唤醒,开始吃饭
            System.out.println("Start eating...");

        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}
复制代码

II、MakeRice.java

/**
 * 做饭
 */
class MakeRice implements Runnable {

    private CountDownLatch countDownLatch;

    public MakeRice(CountDownLatch countDownLatch) {
        this.countDownLatch = countDownLatch;
    }

    public void run() {
        exec();
    }

    /**
     * 模拟做饭
     */
    private void exec() {
        try {
            System.out.println("Start making rice...");

            long millis = ((int)(1+Math.random()*(5-1+1))) * 1000;
            Thread.sleep(millis);
            System.out.println("Making rice is finished.");

            //待处理事情减1
            this.countDownLatch.countDown();

        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}
复制代码

III、MakeDish.java

/**
 * 做菜
 */
class MakeDish implements Runnable {

    private CountDownLatch countDownLatch;

    public MakeDish(CountDownLatch countDownLatch) {
        this.countDownLatch = countDownLatch;
    }

    public void run() {
        exec();
    }

    /**
     * 模拟做菜
     */
    private void exec() {
        try {
            System.out.println("Start making dish...");

            long millis = ((int)(1+Math.random()*(5-1+1))) * 1000;
            Thread.sleep(millis);
            System.out.println("Making dish is finished.");

            //待处理事情减1
            this.countDownLatch.countDown();

        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}
复制代码

IV、CleanUpTable.java

/**
 * 收拾桌子
 */
class CleanUpTable implements Runnable {

    private CountDownLatch countDownLatch;

    public CleanUpTable(CountDownLatch countDownLatch) {
        this.countDownLatch = countDownLatch;
    }

    public void run() {
        exec();
    }

    /**
     * 模拟收拾桌子
     */
    private void exec() {
        try {
            System.out.println("Start making rice...");

            long millis = ((int)(1+Math.random()*(5-1+1))) * 1000;
            Thread.sleep(millis);
            System.out.println("Cleaning up table is finished.");

            //待处理事情减1
            this.countDownLatch.countDown();

        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}
复制代码

V、CountDownLatchTest.java

/**
 * @ClassName CountDownLatchTest
 * @Description 验证CountDownLatch
 * @Author 铿然一叶
 * @Date 2019/10/7 22:32
 * @Version 1.0
 * javashizhan.com
 **/
public class CountDownLatchTest {

    public static void main(String[] args) {

        //为了吃饭,有3件事情要做
        CountDownLatch countDownLatch = new CountDownLatch(3);
        //吃饭活动
        Thread eatingActivity = new Thread(new EatingActivity(countDownLatch));
        eatingActivity.start();

        //做饭
        Thread makeRice = new Thread(new MakeRice(countDownLatch));
        //做菜
        Thread makeDish = new Thread(new MakeDish(countDownLatch));
        //收拾桌子
        Thread cleanUpTable = new Thread(new CleanUpTable(countDownLatch));

        //并行开始做事情
        makeRice.start();
        makeDish.start();
        cleanUpTable.start();
    }
}
复制代码

输出日志:

Waiting for dinner...
Start making rice...
Start making rice...
Start making dish...
Cleaning up table is finished.
Making rice is finished.
Making dish is finished.
Start eating...
复制代码

三、其他场景-拼团

拼团场景中,满多少人后就可以成团,用到了计数器,看起来可以用CountDownLatch来实现,实际上没有必要,因为拼团可以不是并行的,只要有计数器就可以实现。

四、总结

CountDownLatch的适用场景:

1.几件事情完成之后才能开始另外一件事情。

2.需要做的几件事情可以独立完成,并且可以并行处理。

end.

Java并发编程(一)知识地图
Java并发编程(二)原子性
Java并发编程(三)可见性
Java并发编程(四)有序性
Java并发编程(五)创建线程方式概览
Java并发编程入门(六)synchronized用法
Java并发编程入门(七)轻松理解wait和notify以及使用场景
Java并发编程入门(八)线程生命周期
Java并发编程入门(九)死锁和死锁定位
Java并发编程入门(十)锁优化
Java并发编程入门(十一)限流场景和Spring限流器实现
Java并发编程入门(十二)生产者和消费者模式-代码模板
Java并发编程入门(十三)读写锁和缓存模板


站点: javashizhan.com/


微信公众号:


猜你喜欢

转载自juejin.im/post/5d9b5a8de51d4578453274bd
今日推荐