转载

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

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

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

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

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

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

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

二、Show me code

代码类结构如下:

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

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来实现,实际上没有必要,因为拼团可以不是并行的,只要有计数器就可以实现。

原文  https://juejin.im/post/5d9b5a8de51d4578453274bd
正文到此结束
Loading...