JAVA多线程之CountDownLatch和CyclicBarrier

1 CountDownLatch

  • (1)countDownLatch等待指定数量线程结束后,进行下一步;
  • (2)countDownLatch构造函数初始化一个volatile变量,countDown()方法,使用了CAS,和AutomicInteger的增减方法相同;
  • (3)await方法阻塞当前线程,直到getCount值为0,如果不调用countDown方法,getCount的值部位0,那么会一直阻塞。
import java.util.Random;
import java.util.concurrent.CountDownLatch;

// CountDownLatchDemo,运送完5车火石,启动行星发动机
class CountDownLatchDemo
{
     static final int count = 5;

     static CountDownLatch countDownLatch = new CountDownLatch(count);

    public static void main(String[] args)
    {

        for(int i = 0; i < count; i++){
            new Thread(new Runnable()
            {
                @Override
                public void run()
                {
                    try{
                        int t = new Random().nextInt(5000);
                        Thread.sleep(t);
                        System.out.println("耗费" + t + "ms" + "运送完第" + countDownLatch.getCount() + "车火石");
                        countDownLatch.countDown();
                    }catch (InterruptedException e){
                        e.printStackTrace();
                    }

                }
            }).start();
        }
        try
        {
            countDownLatch.await();
            System.out.println("当前阻塞线程数: " + countDownLatch.getCount());
            System.out.println("运送完毕,启动行星发动机");
        }
        catch (InterruptedException e)
        {
            e.printStackTrace();
        }
    }
}

运行结果:

耗费1329ms运送完第5车火石
耗费1775ms运送完第4车火石
耗费2546ms运送完第3车火石
耗费4365ms运送完第2车火石
耗费4531ms运送完第1车火石
当前阻塞线程数: 0
运送完毕,启动行星发动机

Process finished with exit code 0

2 CyclicBarrier
CyclicBarrier也能够实现等待指定数量结束后进行下一步,可以设置屏障,实现诸如:多线程并发–>单线程–>多线程并发,这样的流程。

  • (1)CyclicBarrier的构造函数中,parties表示屏障中最大阻塞的线程数量,Runnable表示下一步操作。
  • (2)CyclicBarrier的await方法将当前线程添加到等待队列中,直到等待队列线程数量达到规定值,才开始进行下一步。
  • (3)getNumberWaiting()方法能够查看当前队列中阻塞的进程数,reset()方法能够清空阻塞的进程数,从头计数,阻塞的线程会抛出broken异常。
  • (4)CyclicBarrier不会阻塞主线程
import java.util.Random;
import java.util.concurrent.CyclicBarrier;

/**
 * 循环屏障demo,集齐10位驾驶员,驾驶员到齐后,运送5车火石,启动行星发动机
 */
public class CyclicBarrierDemo
{
    final static int driver = 10;
    final static int fireStone = 5;

    public static void main(String[] args)
    {
        CyclicBarrierDemo cbd = new CyclicBarrierDemo();
        cbd.barrier1(driver);
        System.out.println("这是主线程");

    }
    //屏障点1,集齐10位驾驶员
    public void barrier1(int num){
        CyclicBarrier cyclicBarrier1 = new CyclicBarrier(num, new Runnable()
        {
            @Override
            public void run()
            {
                System.out.println("驾驶员集齐,开始运送火石");
                barrier2(fireStone);
            }
        });

        for(int i = 0; i < num; i++){
            new Thread(new Runnable()
            {
                @Override
                public void run()
                {
                    try{
                        int t = new Random().nextInt(3000);
                        Thread.sleep(t);
                        System.out.println("驾驶员" +cyclicBarrier1.getNumberWaiting() + "就位");
                        cyclicBarrier1.await();
                    }catch (Exception e){
                        e.printStackTrace();
                    }
                }
            }).start();
        }
    }

    //屏障点2,运送5车火石
    public void barrier2(int num){
        CyclicBarrier cyclicBarrier2 = new CyclicBarrier(num, new Runnable()
        {
            @Override
            public void run()
            {
                System.out.println("启动行星发送机");
            }
        });

        for(int i = 0; i < num; i++){
            new Thread(new Runnable()
            {
                @Override
                public void run()
                {
                    try{
                        int t = new Random().nextInt(3000);
                        Thread.sleep(t);
                        System.out.println("运送火石" +cyclicBarrier2.getNumberWaiting());
                        if(cyclicBarrier2.getNumberWaiting() == 3){
                            cyclicBarrier2.reset();
                            System.out.println("reset后,等待线程数:" + cyclicBarrier2.getNumberWaiting());
                        }
                        cyclicBarrier2.await();
                    }catch (Exception e){
                        e.printStackTrace();
                    }
                }
            }).start();
        }
    }
}

运行结果:

这是主线程
驾驶员0就位
驾驶员1就位
驾驶员2就位
驾驶员3就位
驾驶员4就位
驾驶员5就位
驾驶员6就位
驾驶员7就位
驾驶员8就位
驾驶员9就位
驾驶员集齐,开始运送火石
运送火石0
运送火石1
运送火石2
运送火石3
reset后,等待线程数:0
java.util.concurrent.BrokenBarrierException
	at java.util.concurrent.CyclicBarrier.dowait(CyclicBarrier.java:250)
	at java.util.concurrent.CyclicBarrier.await(CyclicBarrier.java:362)
	at com.study.CyclicBarrierDemo$4.run(CyclicBarrierDemo.java:77)
	at java.lang.Thread.run(Thread.java:748)
java.util.concurrent.BrokenBarrierException
	at java.util.concurrent.CyclicBarrier.dowait(CyclicBarrier.java:250)
	at java.util.concurrent.CyclicBarrier.await(CyclicBarrier.java:362)
	at com.study.CyclicBarrierDemo$4.run(CyclicBarrierDemo.java:77)
	at java.lang.Thread.run(Thread.java:748)
java.util.concurrent.BrokenBarrierException
	at java.util.concurrent.CyclicBarrier.dowait(CyclicBarrier.java:250)
	at java.util.concurrent.CyclicBarrier.await(CyclicBarrier.java:362)
	at com.study.CyclicBarrierDemo$4.run(CyclicBarrierDemo.java:77)
	at java.lang.Thread.run(Thread.java:748)
运送火石1

参考博文:
https://blog.csdn.net/xlgen157387/article/details/78218736

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值