Java并发编程入门(十五)CyclicBarrier应用场景

Java极客  |  做者  /  铿然一叶
这是Java极客的第 43 篇原创文章

1、应用场景

现实生活作中有不少这样的场景:作F前须要等待A,B,C,D,E完成,A,B,C,D,E能够并发完成,没有特定顺序,而且F作完后又从新开始,例如:组装汽车前须要先生产轮胎,车门,车身等等。这个场景的特征为:java

1.组装汽车前有N件事情要作,每件事情都作完后才能组装汽车。编程

2.每件事情能够并行处理,没有前后顺序,于是提升了效率。缓存

3.组装好一辆汽车后继续生产和组装下一辆。(固然如今全部零件都是批量生产,不是一个个来的,咱们假设是人工造的限量版宾利,一量量来的。)安全

围绕造车,整个过程以下:bash


在应用程序中处理并行操做时也跟上述场景相似,碰到这种场景时能够经过java并发工具CyclicBarrier来实现。

2、Show me code

代码类结构以下:并发

I、MakeCarBody.java

public class MakeCarBody implements Runnable {

    private CyclicBarrier cyclicBarrier;

    public MakeCarBody(CyclicBarrier cyclicBarrier) {
        this.cyclicBarrier = cyclicBarrier;
    }

    public void run() {
        exec();
    }

    /** * 模拟模拟造车身 */
    private void exec() {
        //造完后继续造下一个
        while(true) {
            try {
                System.out.println("Start making car body...");

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

                //等待其余部件造完
                this.cyclicBarrier.await();

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

II、MakeCarDoor.java

public class MakeCarDoor implements Runnable {

    private CyclicBarrier cyclicBarrier;

    public MakeCarDoor(CyclicBarrier cyclicBarrier) {
        this.cyclicBarrier = cyclicBarrier;
    }

    public void run() {
        exec();
    }

    /** * 模拟造车门 */
    private void exec() {
        //造完后继续造下一个
        while(true) {
            try {
                System.out.println("Start making car door...");

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

                //等待其余部件造完
                this.cyclicBarrier.await();

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

III、MakeTire.java

public class MakeTire implements Runnable {

    private CyclicBarrier cyclicBarrier;

    public MakeTire(CyclicBarrier cyclicBarrier) {
        this.cyclicBarrier = cyclicBarrier;
    }

    public void run() {
        exec();
    }

    /** * 模拟造轮胎 */
    private void exec() {
        //造完后继续造下一个
        while(true) {
            try {
                System.out.println("Start making tire...");

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

                //等待其余部件造完
                this.cyclicBarrier.await();

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

IV、AssembleCar.java

public class AssembleCar implements Runnable {

    public void run() {
        try {
            System.out.println("Start assemble car...");

            //模拟组装汽车
            long millis = ((int)(1+Math.random()*(5-1+1))) * 1000;
            TimeUnit.MILLISECONDS.sleep(millis);
            System.out.println("Making assemble care is finished.");
        }
        catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}
复制代码

V、CyclicBarrierTest.java

public class CyclicBarrierTest {
    public static void main(String[] args) {
        //有3个部件要造,造完后组装汽车
        CyclicBarrier cyclicBarrier = new CyclicBarrier(3, new AssembleCar());

        Thread makeCarBody = new Thread(new MakeCarBody(cyclicBarrier));
        Thread makeCarDoor = new Thread(new MakeCarDoor(cyclicBarrier));
        Thread makeTire = new Thread(new MakeTire(cyclicBarrier));

        makeCarBody.start();
        makeCarDoor.start();
        makeTire.start();
    }
}
复制代码

输出日志:dom

Start making car door...
Start making tire...
Start making car body...
Making tire is finished.
Making car door is finished.
Making car body is finished.
Start assemble car...
Making assemble care is finished.
Start making car body...
Start making tire...
Start making car door...
Making car body is finished.
Making tire is finished.
Making car door is finished.
Start assemble car...
Making assemble care is finished.
复制代码

能够看到CyclicBarrier的使用方式以下:函数

1.CyclicBarrier的构造函数有2个参数,第1个参数是声明有几个部件须要制造(有几件事能够并行),第2个参数是一个Runnable,此参数表明并行完以后要作的最后一件事情。工具

2.每一个部件造完后调用CyclicBarrier的await()方法等待启动下一轮。post

3.当最后一个部件造完后则会自动调用CyclicBarrier构造函数中传入的Runnable的实现类。

4.Runnable实现类实现完成后从新开始下一轮。

3、总结

CyclicBarrier的适用场景:

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

2.须要作的几件事情能够独立完成,而且能够并行处理。

3.以上事情完成后继续下一轮处理。

end.


相关阅读:
Java并发编程(一)知识地图
Java并发编程(二)原子性
Java并发编程(三)可见性
Java并发编程(四)有序性
Java并发编程(五)建立线程方式概览
Java并发编程入门(六)synchronized用法
Java并发编程入门(七)轻松理解wait和notify以及使用场景
Java并发编程入门(八)线程生命周期
Java并发编程入门(九)死锁和死锁定位
Java并发编程入门(十)锁优化
Java并发编程入门(十一)限流场景和Spring限流器实现
Java并发编程入门(十二)生产者和消费者模式-代码模板
Java并发编程入门(十三)读写锁和缓存模板
Java并发编程入门(十四)CountDownLatch应用场景
Java并发编程入门(十六)秒懂线程池差异
Java并发编程入门(十七)一图掌握线程经常使用类和接口
Java并发编程入门(十八)再论线程安全

相关文章
相关标签/搜索