博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
CyclicBarrier && CountDownLatch
阅读量:4036 次
发布时间:2019-05-24

本文共 2224 字,大约阅读时间需要 7 分钟。

今天写一下这两个类的自己所得吧。

CyclicBarrier(循环屏障):

底层使用的ReetrantLock、LockSupport、AQS、CAS等技术。

使用的含义就是设置指定数量的屏障(通过构造函数赋值),通过await()方法让线程卡在屏障处,实现线程阻塞,阻挡当前线程后续的操作, 当多个线程调用await()方法的个数达到设定的屏障数时,所有的线程都会被唤醒。

线程的阻塞和唤醒使用的LockSupport的park和unpark方法,因为unpark方法可以指定线程进行唤醒。

之所以称之为循环屏障,是因为有个计数器记录调用await()方法的数量,计数器初始值为屏障数,调用一次await()方法就减1,调用次数达到预设的屏障数的时候,计数器会减到0,这个时候释放掉这批线程锁,同时将计数器重新设置为预设的屏障数。

因此,调用await()的线程数必须是预设屏障数的整数倍,才不会有线程在阻塞,否则会有线程在一直阻塞无法释放。

 

 

CountDownLatch(倒计数锁):

核心方法countDown()/await() 方法对。

底层使用的LockSupport、AQS、CAS等技术

await()方法会使用LockSupport.park()方法阻塞线程, 让线程等待

countDown()方法会使用LockSupport.uppark(thread)方法唤醒线程

CountDownLatch有两种使用场景:

1、模拟并发

设置CountDownLatch的初试状态值是1, 创建一堆的并发线程,使用await()等待线程的其他操作, 等待几秒后,主线程使用countDown()方法,唤醒所有线程,同时执行某操作。示例代码:

CountDownLatch cdl = new CountDownLatch(1);for(int i=0;i<50;i++){new Thread(new Runnable() {@Overridepublic void run() {try {cdl.await();} catch (InterruptedException e) {e.printStackTrace();}System.out.println("并发执行====="+Thread.currentThread().getName());}},"我的线程【"+i+"】").start();}try {System.out.println("等待1秒开始并发执行");Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}cdl.countDown();System.out.println("并发执行结束");

 

2、模拟某个线程等待其他线程完成之后进行操作

设置CountDownLatch的初试状态值是是需要执行操作的线程数,每个线程里面,执行完操作之后,调用countDown()方法, 然后在等待的线程中调用await()进行等待,所有线程调用了countDown()之后,await()方法会被唤醒。示例代码:

public static void main(String[] args) throws InterruptedException {CountDownLatch cdl = new CountDownLatch(1000);test2(cdl);}public static void test2(CountDownLatch cdl){long t1 = System.currentTimeMillis();Executor e = new ScheduledThreadPoolExecutor(10);for(int i=0;i<1000;i++){e.execute(new MyWork(cdl,i));}try {cdl.await();} catch (InterruptedException e1) {e1.printStackTrace();}long t2 = System.currentTimeMillis();System.out.println("耗时:" + (t2 - t1) + "ms============"+cdl.getCount());}static class MyWork implements Runnable {private CountDownLatch cd;private int i;public MyWork(CountDownLatch cd, int i) {this.cd = cd;this.i = i;}@Overridepublic void run() {doWork(i);try {Thread.sleep(200);} catch (InterruptedException e) {e.printStackTrace();}cd.countDown();}private void doWork(int i) {System.out.println("这是第" + i + "个循环,线程为" + Thread.currentThread().getName()+"==="+cd.getCount());}}

 

 

转载地址:http://zqcdi.baihongyu.com/

你可能感兴趣的文章
VC的MFC里面控件的ID使用ID_XXXXX和IDR_XXXXX的区别
查看>>
VC++ 获取ListControl选中行
查看>>
用VC++实现应用程序窗口的任意分割(2)
查看>>
“class”类型重定义,include(头文件)重复加载 QT /c++
查看>>
MFC框架类、文档类、视图类相互访问的方法
查看>>
<转>文档视图指针互获
查看>>
C++中头文件相互包含的几点问题
查看>>
内存设备描述表
查看>>
Latex插入eps图片的方法
查看>>
Matlab subplot 图像间距调整
查看>>
Hibernate使用count(*)取得表中记录总数
查看>>
distinct使SQL查询除去重复的字段
查看>>
从mysql中 导出/导入表及数据
查看>>
HQL语句大全(转)
查看>>
几个常用的Javascript字符串处理函数 spilt(),join(),substring()和indexof()
查看>>
javascript传参字符串 与引号的嵌套调用
查看>>
进程的状态
查看>>
Runnable和Thread 两种实现方式的区别和联系:
查看>>
并发和并行的区别
查看>>
JAVA多线程和并发基础面试问答
查看>>