同步工具:CountDownLatch、CyclicBarrier和Semaphore
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的更多相关文章
- 并发编程学习笔记(10)----并发工具类CyclicBarrier、Semaphore和Exchanger类的使用和原理
在jdk中,为并发编程提供了CyclicBarrier(栅栏),CountDownLatch(闭锁),Semaphore(信号量),Exchanger(数据交换)等工具类,我们在前面的学习中已经学习并 ...
- Java核心知识点学习----线程同步工具类,CyclicBarrier学习
线程同步工具类,CyclicBarrier日常开发较少涉及,这里只举一个例子,以做备注.N个人一块出去玩,相约去两个地方,CyclicBarrier的主要作用是等待所有人都汇合了,才往下一站出发. 1 ...
- CountDownLatch CyclicBarrier和 Semaphore
CountDownLatch CyclicBarrier和 Semaphore 原理 基于AQS实现. 让需要的暂时阻塞的线程,进入一个死循环里面,得到某个条件后再退出循环,以此实现阻塞当前线程的效果 ...
- Java并发和多线程4:使用通用同步工具CountDownLatch实现线程等待
CountDownLatch,一个同步辅助类,在完成一组正在其他线程中执行的操作之前,它允许一个或多个线程一直等待. 用给定的计数 初始化 CountDownLatch.由于调用了 countDown ...
- Java多线程_同步工具CountDownLatch
概念:CountDownLatch是多线程里面一个类似于计数器的高级同步工具,它的初始值代表线程的数量,当一个线程完成了任务后,CountDownLatch的值就减1,当值为0的时候,代表所有线程完成 ...
- CountDownLatch, CyclicBarrier and Semaphore
Reference: [1] http://shazsterblog.blogspot.co.uk/2011/12/comparison-of-countdownlatch.html CountDow ...
- java多线程系列9 高级同步工具(3) CyclicBarrier
CyclicBarrier 一个同步辅助类,它允许一组线程互相等待,直到到达某个公共屏障点 (common barrier point) 然后一再执行 public class CyclicBar ...
- 线程同步工具CountDownLatch
CountDownLatch的一个非常典型的应用场景是:有一个任务想要往下执行,但必须要等到其他的任务执行完毕后才可以继续往下执行.假如我们这个想要继续往下执行的任务调用一个CountDownLatc ...
- JAVA多线程提高十:同步工具CyclicBarrier与CountDownLatch
今天继续学习其它的同步工具:CyclicBarrier与CountDownLatch 一.CyclicBarrier CyclicBarrier是一个同步辅助类,它允许一组线程互相等待,直到到达某个公 ...
随机推荐
- 斯坦福HAI—细数全球18件AI大事记
3 月 18 日,由李飞飞担任所长之一的「以人为本人工智能研究所」(HAI)自启动以来不短的时间后,终于完成了正式成立的高光时刻.而正式上线的官网日前也更新了两条博文,一篇是详尽介绍 HAI 的文章: ...
- 超简单Mac安装Tomcat服务器
超简单Mac安装Tomcat服务器 1.首先下载tomcat 下载连接 2. 解压并改名 3.把Tomcat复制到系统中的资源库或者Library 4.打开shell,进入Tomcat下面的bin目录 ...
- Web安全入门学习
前言 最近在公司做Linux下的PHP开发,所以乘此机会学习了下Web安全,了解了常见的Web安全漏洞,以及对应的防御方法(使用DVWA进行学习). 暴力破解 场景 在类似用户登陆界面 ...
- github打开慢,甚至打不开
有人使用github后,在某些网络下发现打开慢,甚至打不开,这都是因为他是国外站:目前互联网的连接机制导致超过一定的路由节点的连接就会出现这个问题,解决办法就是直接告诉本机ip.不要先层层询问域名转i ...
- linux系统原子操作
一.概念 原子操作提供了指令原子执行,中间没有中断.就像原子被认为是不可分割颗粒一样,原子操作(atomic operation)是不可分割的操作. c语言中一个变量的自加1操作,看起来很简 ...
- Luogu4886 快递员 点分治
传送门 淀粉质好题啊qaq 我们先考虑随便选择一个点作为邮递中心,通过移动邮递中心找到更优的位置.将路径最大值求出,并将路径最大值对应的那一些路径拿出来考虑.可以知道,如果说这些路径中存在一条经过当前 ...
- python3通过gevent.pool限制协程并发数量
协程虽然是轻量级的线程,但到达一定数量后,仍然会造成服务器崩溃出错.最好的方法通过限制协程并发数量来解决此类问题. server代码: #!/usr/bin/env python # -*- codi ...
- asp.net mvc 实现上传文件带进度条
本文乃是博主早期写的,此种思路虽然实现了,但固然不是最好的,仅做参考学习. 可以用js onprogress .fileinput .webuploader.jq ajaxsubmit等实现 思路:a ...
- windows下docker启动.net core mvc随手记
docker基本命令: 查看当前的版本docker--version查看本地所有镜像:docker images查看当前正在运行的所有容器docker ps停止某个容器:docker stop 容器I ...
- Object-Oriented(二)原型对象
自用备忘笔记 1. 理解原型对象 只要创建函数,函数上就会创建一个 prototype 属性指向函数的原型对象. function Person() {} Person.prototype //指向该 ...