jdk-CyclicBarrier(二)

jdk-CyclicBarrier这一篇主要是分析了它 的源码和运行图。这一篇来看看怎么运用,毕竟都是要使用的。

上文在分析源码过程中发现有个代数的问题,在nextGeneration中会有下一代的出现,这个是否就是说它是可以重用的?不然哪会来区分一代,二代,三代呢?

例子1:次例子中重复使用了CyclicBarrier

public class TestCycB {

    private static int num = 3;

    public static void main(String[] args) throws Exception{

        final CyclicBarrier cb = new CyclicBarrier(num);

        for(int i = 0; i < 3; i ++){
            new EachThread(cb).start();
        }
        Thread.sleep(10000);
        System.out.println("主线程休息够了,燥起来");

        for(int i = 0; i < 3; i ++){
            new EachThread(cb).start();
        }

    }
}

class EachThread extends Thread{

    private CyclicBarrier cb;

    public EachThread(CyclicBarrier cb){
        this.cb = cb;
    }

    @Override
    public void run() {
        try{
            Thread.sleep(2000);
            System.out.println(Thread.currentThread().getName()+"进入等待");
            cb.await();
            Thread.sleep(2000);
            System.out.println(Thread.currentThread().getName()+"等待结束了,执行起来");
        }catch (InterruptedException e){
            e.printStackTrace();
        }catch (BrokenBarrierException e1){
            e1.printStackTrace();
        }
    }

}

Thread-0进入等待
Thread-2进入等待
Thread-1进入等待
Thread-1等待结束了,执行起来
Thread-0等待结束了,执行起来
Thread-2等待结束了,执行起来
主线程执行
Thread-3进入等待
Thread-5进入等待
Thread-4进入等待
Thread-4等待结束了,执行起来
Thread-3等待结束了,执行起来
Thread-5等待结束了,执行起来

例子2,使用timeout,timeout是指虽然全部线程没有完全进入,但是超过这个超时时间的话,立马执行其余线程,这些线程会抛出异常,然后继续执行.

public class TestCycB {

    private static int num = 3;

    public static void main(String[] args) throws Exception{

        final CyclicBarrier cb = new CyclicBarrier(num);

        for(int i = 0; i < 3; i ++){
            Thread.sleep(3000);
            new EachThread(cb).start();
        }
    }
}

class EachThread extends Thread{

    private CyclicBarrier cb;

    public EachThread(CyclicBarrier cb){
        this.cb = cb;
    }

    @Override
    public void run() {
        System.out.println(Thread.currentThread().getName()+"进入初始化");
        try{
            Thread.sleep(2000);//模拟初始化
            System.out.println(Thread.currentThread().getName() + "初始化结束,进入等待");
            cb.await(3, TimeUnit.SECONDS);  //睡3
        }catch (InterruptedException e){
            e.printStackTrace();
        }catch (BrokenBarrierException e1){
            e1.printStackTrace();
        }catch (TimeoutException e2){
            e2.printStackTrace();
        }
        System.out.println(Thread.currentThread().getName()+"等待结束了,执行起来");
    }

}


Thread-0进入初始化
Thread-0初始化结束,进入等待
Thread-1进入初始化
java.util.concurrent.TimeoutException
Thread-1初始化结束,进入等待
	at java.util.concurrent.CyclicBarrier.dowait(CyclicBarrier.java:250)
Thread-0等待结束了,执行起来
	at java.util.concurrent.CyclicBarrier.await(CyclicBarrier.java:427)
Thread-1等待结束了,执行起来
	at concurrenttest.EachThread.run(TestCycB.java:40)
java.util.concurrent.BrokenBarrierException
	at java.util.concurrent.CyclicBarrier.dowait(CyclicBarrier.java:243)
	at java.util.concurrent.CyclicBarrier.await(CyclicBarrier.java:427)
	at concurrenttest.EachThread.run(TestCycB.java:40)
Thread-2进入初始化
java.util.concurrent.BrokenBarrierException
	at java.util.concurrent.CyclicBarrier.dowait(CyclicBarrier.java:200)
	at java.util.concurrent.CyclicBarrier.await(CyclicBarrier.java:427)
	at concurrenttest.EachThread.run(TestCycB.java:40)
Thread-2初始化结束,进入等待
Thread-2等待结束了,执行起来

例子3,自定义任务,自定义任务的执行是由最终进入的线程执行的,源码中可以看见,并且这个任务是优先于其他等待线程.
public class TestCycB {

    private static int num = 3;

    public static void main(String[] args) throws Exception{

        final CyclicBarrier cb = new CyclicBarrier(num,new Runnable() {
            @Override
            public void run() {
                try{
                Thread.sleep(5000);
                }catch (Exception e){
                    e.printStackTrace();
                }
                System.out.println(Thread.currentThread().getName()+"自带任务的执行");
            }
        });

        for(int i = 0; i < 3; i ++){
            new EachThread(cb).start();
        }
    }
}

class EachThread extends Thread{

    private CyclicBarrier cb;

    public EachThread(CyclicBarrier cb){
        this.cb = cb;
    }

    @Override
    public void run() {
        System.out.println(Thread.currentThread().getName()+"进入初始化");
        try{
            Thread.sleep(2000);//模拟初始化
            System.out.println(Thread.currentThread().getName() + "初始化结束,进入等待");
            cb.await();
        }catch (InterruptedException e){
            e.printStackTrace();
        }catch (BrokenBarrierException e1){
            e1.printStackTrace();
        }
        System.out.println(Thread.currentThread().getName()+"等待结束了,执行起来");
    }

}

Thread-0进入初始化
Thread-2进入初始化
Thread-1进入初始化
Thread-0初始化结束,进入等待
Thread-2初始化结束,进入等待
Thread-1初始化结束,进入等待
Thread-2自带任务的执行
Thread-0等待结束了,执行起来
Thread-1等待结束了,执行起来
Thread-2等待结束了,执行起来

例子4: 可以发现自带任务先执行完,最后才指向其他任务。

public class TestCycB {

    private static int num = 3;

    public static void main(String[] args) throws Exception{

        final CyclicBarrier cb = new CyclicBarrier(num,new Runnable() {
            @Override
            public void run() {
                try{
                    Thread.sleep(10000);
                }catch (Exception e){
                    e.printStackTrace();
                }

                System.out.println("自带任务执行了");
            }
        });

        for(int i = 0; i < 3; i ++){
            new EachThread(cb).start();
        }
    }
}

class EachThread extends Thread{

    private CyclicBarrier cb;

    public EachThread(CyclicBarrier cb){
        this.cb = cb;
    }

    @Override
    public void run() {
        System.out.println(Thread.currentThread().getName()+"进入初始化");
        try{
            System.out.println(Thread.currentThread().getName() + "初始化结束,进入等待");
            cb.await(1, TimeUnit.SECONDS);  //睡3
        }catch (InterruptedException e){
            e.printStackTrace();
        }catch (BrokenBarrierException e1){
            e1.printStackTrace();
        }catch (TimeoutException e2){
            e2.printStackTrace();
        }
        System.out.println(Thread.currentThread().getName()+"等待结束了,执行起来");
    }

}

Thread-2进入初始化
Thread-2初始化结束,进入等待
Thread-1进入初始化
Thread-1初始化结束,进入等待
Thread-0进入初始化
Thread-0初始化结束,进入等待
自带任务执行了
Thread-0等待结束了,执行起来
Thread-2等待结束了,执行起来
Thread-1等待结束了,执行起来


例子5:自带任务抛异常。
public class TestCycB {

    private static int num = 3;

    public static void main(String[] args) throws Exception{

        final CyclicBarrier cb = new CyclicBarrier(num,new Runnable() {
            @Override
            public void run() {
                try{
                    Thread.sleep(6000);
                    System.out.println("自带任务执行了:抛异常");
                    int j = 1 /0;
                }catch (Exception e){
                    e.printStackTrace();
                }


            }
        });

        for(int i = 0; i < 3; i ++){
            new EachThread(cb).start();
        }
    }
}

class EachThread extends Thread{

    private CyclicBarrier cb;

    public EachThread(CyclicBarrier cb){
        this.cb = cb;
    }

    @Override
    public void run() {
        System.out.println(Thread.currentThread().getName()+"进入初始化");
        try{
            Thread.sleep(2000);
            System.out.println(Thread.currentThread().getName() + "初始化结束,进入等待");
            cb.await();  //睡3
        }catch (InterruptedException e){
            e.printStackTrace();
        }catch (BrokenBarrierException e1){
            e1.printStackTrace();
        }
        System.out.println(Thread.currentThread().getName()+"等待结束了,执行起来");
    }

}


Thread-0进入初始化
Thread-2进入初始化
Thread-1进入初始化
Thread-2初始化结束,进入等待
Thread-0初始化结束,进入等待
Thread-1初始化结束,进入等待
自带任务执行了:抛异常
Thread-1等待结束了,执行起来
Thread-2等待结束了,执行起来
Thread-0等待结束了,执行起来
java.lang.ArithmeticException: / by zero
	at concurrenttest.TestCycB$1.run(TestCycB.java:25)
	at java.util.concurrent.CyclicBarrier.dowait(CyclicBarrier.java:213)
	at java.util.concurrent.CyclicBarrier.await(CyclicBarrier.java:355)
	at concurrenttest.EachThread.run(TestCycB.java:54)

最后来比较下CountDownLatch和CyclicBarrier的一些不同点。。

拿赛跑来说吧,这是个比较典型的例子。

场景1:5个人赛跑,还有一个裁判,当裁判说开始时,5个人起跑,当某一个人到达终点后,裁判按一下计数器,直至最后一个人到达,最后裁判才开始统计时间,得到每个人的时间。这个就是CountDownLatch的运用。

场景2:还是5个人赛跑,这一次没有裁判了,只规定如果5个人到达终点后,一起去喝酒这个就是CyclicBarrier的运用,此例子中没有说是否需要一起起跑,如果需要,可以加上CountDownLatch。

CountDownLatch就是一个线程等待其他线程都完成之后,再执行某些事情,强调这个。

CyclicBarrier强调线程互相等待,等待全部完成。



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值