1. CountDownLatch

1.1 功能及使用场景

一个同步工具,使得一个或多个线程等待一组线程执行完成后再执行。

使用场景:等待一些前置任务执行完成后,再执行特定的功能。比如,系统启动时,各种配置生效后,才能运行提供服务。

1.2 代码实例

public class CountDownLatchTest {

    public static void main(String[] args) {
final CountDownLatch latch = new CountDownLatch(5); for (int i = 0; i < 5; i++) {
new Thread(new Runnable() {
@Override
public void run() {
try {
TimeUnit.SECONDS.sleep(new Random().nextInt(10));
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + " end, " + System.currentTimeMillis());
latch.countDown();
}
}).start();
} try {
System.out.println("main latch.await() " + System.currentTimeMillis());
latch.await();
System.out.println("main latch.await() end " + System.currentTimeMillis());
} catch (InterruptedException e) {
e.printStackTrace();
} } }

特别注意:CountDownLatch初始化时,数量一定要等于等待的线程的数量。

2. CyclicBarrier

2.1 功能及使用场景

CyclicBarrier(可循环同步屏障),控制一组线程相互等待,直到所有线程都到达屏障点。所有线程都到达屏障点后,同时开始执行剩余的任务。

可循环,意味着当所有线程都到达屏障后,屏障可以被再次重复利用。

使用场景

多个任务同时到达某个临界情况时,才能同时执行剩余任务,否则相互等待。

2.2 示例代码

public class CyclicBarrierTest {

    public static void main(String[] args) {
int num = 3;
final CyclicBarrier barrier = new CyclicBarrier(num);
for (int i = 0; i < num; i++) {
new Thread(new Runnable() {
@Override
public void run() {
try {
TimeUnit.SECONDS.sleep(new Random().nextInt(5));
System.out.println(Thread.currentThread().getName() + "执行结束,开始等待其它线程, " + System.currentTimeMillis());
barrier.await();
System.out.println(Thread.currentThread().getName() + "所有线程等待都执行完成,开始执行剩下任务, " + System.currentTimeMillis());
} catch (InterruptedException e) {
e.printStackTrace();
} catch (BrokenBarrierException e) {
e.printStackTrace();
}
}
}).start();
} // 屏障可以在上一次使用完成后被再次使用
for (int i = 0; i < num; i++) {
new Thread(new Runnable() {
@Override
public void run() {
try {
TimeUnit.SECONDS.sleep(new Random().nextInt(5));
System.out.println(Thread.currentThread().getName() + "执行结束,开始等待其它线程, " + System.currentTimeMillis());
barrier.await();
System.out.println(Thread.currentThread().getName() + "所有线程等待都执行完成,开始执行剩下任务, " + System.currentTimeMillis());
} catch (InterruptedException e) {
e.printStackTrace();
} catch (BrokenBarrierException e) {
e.printStackTrace();
}
}
}).start();
}
System.out.println("main end at " + System.currentTimeMillis());
} }

3. Semaphore

3.1 功能及使用场景

Semaphore(信号量),一个计数信号量。概念上,一个信号量维持了一个许可集合。

  • acquire()方法:获取一个许可,如果没有获取到许可,则一直阻塞到获得一个许可;
  • release()方法:归还一个许可。

实际上,并没有真正的许可对象,只是计数。

使用场景

限制资源同时被访问的线程数量

3.2 使用代码

public class SemaphoreTest {

    public static void main(String[] args) {
final Semaphore semaphore = new Semaphore(3);
for (int i = 0; i < 10; i++) {
new Thread(new Runnable() {
@Override
public void run() {
try {
System.out.println(Thread.currentThread().getName() + "尝试获取许可, " + System.currentTimeMillis());
semaphore.acquire();
System.out.println(Thread.currentThread().getName() + "获取许可, " + System.currentTimeMillis());
TimeUnit.SECONDS.sleep(new Random().nextInt(5));
System.out.println(Thread.currentThread().getName() + "执行结束, " + System.currentTimeMillis());
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
semaphore.release();
}
}
}).start();
}
System.out.println("main end! " + System.currentTimeMillis());
} }

特别注意:获得许可并执行完逻辑后,一定要释放,否则许可不会被归还。(有借有还,再借不难)

4. 总结

  • CountDownLatch:一个任务等待前置任务执行完后才能执行
  • CyclicBarrier: 一组任务相互等待,直到所有线程均到达某个临界状态
  • Semaphore: 一组许可,控制资源被同时访问的数量(获取许可,也要归还许可)

同步工具:CountDownLatch、CyclicBarrier和Semaphore的更多相关文章

  1. 并发编程学习笔记(10)----并发工具类CyclicBarrier、Semaphore和Exchanger类的使用和原理

    在jdk中,为并发编程提供了CyclicBarrier(栅栏),CountDownLatch(闭锁),Semaphore(信号量),Exchanger(数据交换)等工具类,我们在前面的学习中已经学习并 ...

  2. Java核心知识点学习----线程同步工具类,CyclicBarrier学习

    线程同步工具类,CyclicBarrier日常开发较少涉及,这里只举一个例子,以做备注.N个人一块出去玩,相约去两个地方,CyclicBarrier的主要作用是等待所有人都汇合了,才往下一站出发. 1 ...

  3. CountDownLatch CyclicBarrier和 Semaphore

    CountDownLatch CyclicBarrier和 Semaphore 原理 基于AQS实现. 让需要的暂时阻塞的线程,进入一个死循环里面,得到某个条件后再退出循环,以此实现阻塞当前线程的效果 ...

  4. Java并发和多线程4:使用通用同步工具CountDownLatch实现线程等待

    CountDownLatch,一个同步辅助类,在完成一组正在其他线程中执行的操作之前,它允许一个或多个线程一直等待. 用给定的计数 初始化 CountDownLatch.由于调用了 countDown ...

  5. Java多线程_同步工具CountDownLatch

    概念:CountDownLatch是多线程里面一个类似于计数器的高级同步工具,它的初始值代表线程的数量,当一个线程完成了任务后,CountDownLatch的值就减1,当值为0的时候,代表所有线程完成 ...

  6. CountDownLatch, CyclicBarrier and Semaphore

    Reference: [1] http://shazsterblog.blogspot.co.uk/2011/12/comparison-of-countdownlatch.html CountDow ...

  7. java多线程系列9 高级同步工具(3) CyclicBarrier

    CyclicBarrier 一个同步辅助类,它允许一组线程互相等待,直到到达某个公共屏障点 (common barrier point)   然后一再执行 public class CyclicBar ...

  8. 线程同步工具CountDownLatch

    CountDownLatch的一个非常典型的应用场景是:有一个任务想要往下执行,但必须要等到其他的任务执行完毕后才可以继续往下执行.假如我们这个想要继续往下执行的任务调用一个CountDownLatc ...

  9. JAVA多线程提高十:同步工具CyclicBarrier与CountDownLatch

    今天继续学习其它的同步工具:CyclicBarrier与CountDownLatch 一.CyclicBarrier CyclicBarrier是一个同步辅助类,它允许一组线程互相等待,直到到达某个公 ...

随机推荐

  1. MyBatis+Hibernate+JDBC对比分析

    MyBatis目前作为持久层,用的最多,因为它符合互联网开发的变动性,实际开发中需求总会有这样的,那样的变动,MyBatis虽然没有Hibernate那么全自动化,而且对于开发人员的sql能力要求比较 ...

  2. Spring Security 重定向原理分析

    本文基于 spring-security-core-5.1.1 和 tomcat-embed-core-9.0.12. 一个用户访问使用表单认证的 Web 应用时,后端的处理流程大致如下: 1.用户访 ...

  3. VUE2 第五天学习--过渡效果

    阅读目录 1.理解VUE---过渡效果 回到顶部 1.理解VUE---过渡效果 1. 过渡的-css-类名会有4个(css) 类名在 enter/leave 在过渡中切换.1. v-enter: 进入 ...

  4. hibernate4使用原生jdbc进行批处理

    在hibernate中,有一级缓存session和二级缓存sessionFactory这些机制,一方面为编码提供了便利,同时也会有一些副作用.比如有较大的数据量交互的话,缓存反而会降低效率.最近在做一 ...

  5. STL语法——集合:set 安迪的第一个字典(Andy's First Dictionary,UVa 10815)

    Description Andy, , has a dream - he wants to produce his very own dictionary. This is not an easy t ...

  6. java中使用jxl读取excel中的数据

    package bboss; import java.io.File; import java.io.FileInputStream; import java.io.IOException; impo ...

  7. odoo 装饰器用法@api

    摘自:blog.csdn.net/cmzhuang/article/details/52932883 @api.one one装饰符自动遍历记录集,把self重新定义成当前记录.注意,返回值是一个li ...

  8. 新页面,简单的tree视图写法

    .xml文件 <?xml version="1.0"?><openerp> <data> <!--Tree view--> < ...

  9. Promise使用时应注意的问题

    最近在使用axios库时遇到了个问题,后端接口报了500错误,但前端并未捕获到.1. 调用接口的业务代码如下: // 业务代码调用 axios({ url: url, method: 'post', ...

  10. 【php增删改查实例】第十八节 - login.php编写

    1.对用户名和密码进行非空判断(后台验证) $username; $password; if(isset($_POST['username']) && $_POST['username ...