【Java多线程】JUC包下的工具类CountDownLatch、CyclicBarrier和Semaphore
前言
JUC中为了满足在并发编程中不同的需求,提供了几个工具类供我们使用,分别是CountDownLatch、CyclicBarrier和Semaphore,其原理都是使用了AQS来实现,下面分别进行介绍。
CountDownLatch
CountDownLatch的主要作用是利用计数来保证线程的执行顺序(我自己的理解),有点像倒计时,当计数为0时某个线程才能开始执行。
CountDownLatch的主要方法很简单易用,包括:
- CountDownLatch(int count) : 构造方法,需要传入计数的初始值
- void await() : 调用者线程会被挂起,直到计数为0时才能执行
- boolean await(long timeout, TimeUnit unit) : 同上,但是加入了超时参数,如果超时了计数还不为0,也会照样执行,避免了一直阻塞
- void countDown() : 计数减一
示例代码:CountDownLatchTest.java
package juc.util;
import java.util.concurrent.CountDownLatch;
/**
* Created by puyangsky on 2017/1/7.
*/
public class CountDownLatchTest {
public static void main(String[] args) {
final CountDownLatch latch = new CountDownLatch(2);
//用了匿名类创建线程
new Thread() {
public void run() {
try {
System.out.println("子线程"+Thread.currentThread().getName()+"正在执行");
Thread.sleep(2000);
System.out.println("子线程"+Thread.currentThread().getName()+"执行完毕");
latch.countDown();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}.start();
new Thread() {
public void run() {
try {
System.out.println("子线程"+Thread.currentThread().getName()+"正在执行");
Thread.sleep(2000);
System.out.println("子线程"+Thread.currentThread().getName()+"执行完毕");
latch.countDown();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}.start();
System.out.println("主线程"+Thread.currentThread().getName()+"正在执行");
try {
latch.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("主线程"+Thread.currentThread().getName()+"执行完毕");
}
}
结果:
主线程main正在执行
子线程Thread-0正在执行
子线程Thread-1正在执行
子线程Thread-0执行完毕
子线程Thread-1执行完毕
主线程main执行完毕
可以从结果中看到主线程本来是最先执行完,结果需要等两个子线程执行完才结束,就是因为调用了await方法。
CyclicBarrier
CyclicBarrier的意思是回环栅栏,作用是让一组线程同时到达某个时间节点。提供的重要方法如下:
- CyclicBarrier(int parties) : 构造方法,传入线程组的数量
- CyclicBarrier(int parties, Runnable barrierAction) : 构造方法,传入线程组的数量和当线程达到时间节点后要做的操作(由其中的某一个线程去执行)
- int await() : 挂起当前线程,直到所有线程组中的线程都完成后继续执行,返回当前线程到达的次序
- int await(long timeout, TimeUnit unit) : 加了一个超时参数
示例代码 CyclicBarrierTest.java:
package juc.util;
import java.util.concurrent.BrokenBarrierException;
import java.util.concurrent.CyclicBarrier;
/**
* Created by puyangsky on 2017/1/7.
*/
public class CyclicBarrierTest {
public static void main(String[] args) {
CyclicBarrier barrier = new CyclicBarrier(5, new Runnable() {
@Override
public void run() {
System.out.println("当前线程"+Thread.currentThread().getName());
}
});
for (int i=0;i<5;i++) {
new Task(barrier).start();
}
}
static class Task extends Thread {
private CyclicBarrier barrier;
public Task(CyclicBarrier barrier) {
this.barrier = barrier;
}
public void run() {
System.out.println("子线程"+Thread.currentThread().getName()+"正在执行");
try {
Thread.sleep(3000);
System.out.println("子线程"+Thread.currentThread().getName()+"执行完成");
barrier.await();
} catch (InterruptedException e) {
e.printStackTrace();
} catch (BrokenBarrierException e) {
e.printStackTrace();
}
System.out.println("全部线程执行完成");
}
}
}
结果:
子线程Thread-0正在执行
子线程Thread-3正在执行
子线程Thread-2正在执行
子线程Thread-1正在执行
子线程Thread-4正在执行
子线程Thread-3执行完成
子线程Thread-2执行完成
子线程Thread-0执行完成
子线程Thread-1执行完成
子线程Thread-4执行完成
当前线程Thread-4
全部线程执行完成
全部线程执行完成
全部线程执行完成
全部线程执行完成
全部线程执行完成
可以看到这一组线程是同步的去执行的。
Semaphore
Semaphore的意思是信号量,其作用是提供一个许可范围,只有获得了许可才能继续执行。
- Semaphore(int permits):构造方法,需要传入许可数
- Semaphore(int permits, boolean fair):fair为true时使用公平锁,false时使用非公平锁,具体在介绍AQS时讲解
- void acquire():获得许可,可中断
- void acquireUninterruptibly():不可中断的获取
- void release():释放许可
示例 SemaphoreTest.java
package juc.util;
import java.util.concurrent.Semaphore;
/**
* Created by puyangsky on 2017/1/7.
*/
public class SemaphoreTest {
public static void main(String[] args) {
Semaphore semaphore = new Semaphore(5);
for (int i = 0;i < 10;i++) {
new Worker(i, semaphore).start();
}
}
static class Worker extends Thread {
private Semaphore semaphore;
private int num;
public Worker(int num, Semaphore semaphore) {
this.semaphore = semaphore;
this.num = num;
}
public void run() {
try {
semaphore.acquire();
System.out.println("工人" + (this.num + 1) + "占用一个机器在生产...");
Thread.sleep(2000);
System.out.println("工人" + (this.num + 1) + "释放一个机器...");
semaphore.release();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
结果
工人1占用一个机器在生产...
工人3占用一个机器在生产...
工人4占用一个机器在生产...
工人5占用一个机器在生产...
工人7占用一个机器在生产...
工人1释放一个机器...
工人5释放一个机器...
工人4释放一个机器...
工人7释放一个机器...
工人3释放一个机器...
工人8占用一个机器在生产...
工人9占用一个机器在生产...
工人10占用一个机器在生产...
工人6占用一个机器在生产...
工人2占用一个机器在生产...
工人9释放一个机器...
工人6释放一个机器...
工人10释放一个机器...
工人8释放一个机器...
工人2释放一个机器...
可以看到每次只有五个线程能运行,其他线程只有等待这五个线程释放许可后才能运行。
参考文章:
【Java多线程】JUC包下的工具类CountDownLatch、CyclicBarrier和Semaphore的更多相关文章
- Java中的4个并发工具类 CountDownLatch CyclicBarrier Semaphore Exchanger
在 java.util.concurrent 包中提供了 4 个有用的并发工具类 CountDownLatch 允许一个或多个线程等待其他线程完成操作,课题点 Thread 类的 join() 方法 ...
- java.util.regex包下的Pattern类和Matcher类的使用总结
一.介绍 Java正则表达式通过java.util.regex包下的Pattern类与Matcher类实现1.Pattern类用于创建一个正则表达式,也可以说创建一个匹配模式,它的构造方法是私有的,不 ...
- Java并发编程工具类 CountDownLatch CyclicBarrier Semaphore使用Demo
Java并发编程工具类 CountDownLatch CyclicBarrier Semaphore使用Demo CountDownLatch countDownLatch这个类使一个线程等待其他线程 ...
- Java 获取指定包下的所有类
package com.s.rest.util; import java.io.File; import java.io.FileFilter; import java.io.IOException; ...
- 并发包下常见的同步工具类(CountDownLatch,CyclicBarrier,Semaphore)
在实际开发中,碰上CPU密集且执行时间非常耗时的任务,通常我们会选择将该任务进行分割,以多线程方式同时执行若干个子任务,等这些子任务都执行完后再将所得的结果进行合并.这正是著名的map-reduce思 ...
- java 并发工具类CountDownLatch & CyclicBarrier
一起在java1.5被引入的并发工具类还有CountDownLatch.CyclicBarrier.Semaphore.ConcurrentHashMap和BlockingQueue,它们都存在于ja ...
- Java多线程_JUC包下的阻塞队列
在前面我们提到了阻塞队列,也用过了LinkedBolckingQueue队列了,在这里,我们主要对 ArrayBlockingQueue,PriorityBlockingQueue,DelayQueu ...
- java多线程系列8 高级同步工具(2)CountDownLatch
CountDownLatch,计数器的初始值为线程的数量.每当一个线程完成了自己的任务后, 计数器的值就会减1.当计数器值到达0时,它表示所有的线程已经完成了任务, 然后在闭锁上等待的线程就可以恢复执 ...
- java.util.regex包下的Pattern和Matcher详解(正则匹配)
java正则表达式通过java.util.regex包下的Pattern类与Matcher类实现(建议在阅读本文时,打开java API文档,当介绍到哪个方法时,查看java API中的方法说明,效果 ...
随机推荐
- android: 接收和发送短信
8.2 接收和发送短信 收发短信应该是每个手机最基本的功能之一了,即使是许多年前的老手机也都会具备这 项功能,而 Android 作为出色的智能手机操作系统,自然也少不了在这方面的支持.每个 A ...
- RFID 读写器 Reader Writer Cloner
RFID读写器的工作原理 RFID的数据采集以读写器为主导,RFID读写器是一种通过无线通信,实现对标签识别和内存数据的读出和写入操作的装置. 读写器又称为阅读器或读头(Reader).查询器(Int ...
- mysqld.exe 占了400M内存的问题
最近遇到了服务器总是停机的问题,虽然它自己只有2G的内存,不过实际部署的应用访问量非常小,也不至于2G就不够用,所以开始了给服务器瘦身的计划. 看着任务管理器里面的各个进程,发现吃内存最厉害的是mys ...
- 在cxf中使用配置避免增加字段导致客户端必须更新、同步实体属性的问题
在使用cxf实现webservice时,经常碰到的问题就是如果在服务端,修改了一个接口的签名实现,如增加一个字段,或者删除一个字段.在这种情况下,在默认的配置中,就会报以下的错误信息: org.apa ...
- asp.net 操作excel的一系列问题(未完待续)
最近在处理exel的一些东西,遇到了很多问题,现在就在此将问题和网上找到的解决办法 1.外部表不是预期格式错误 错误经过:在读取Excel时,出现外部表不是预期的格式 错误原因1: 由于Excel 9 ...
- 黄页js-sdk开发总结分享
2014年,为了方便第三方开发者能够调用本地的一些功能,我们提供了一套js-sdk.通过调用我们的接口,开发者可以定制UI,获取当前的手机状态,调用支付,黄页扫一扫功能,为用户提供更加优质的体验.下面 ...
- JAVA中类、实例与Class对象
已同步更新至个人blog:http://dxjia.cn/2015/08/java-class-object/ 类 类是面向对象编程语言的一个重要概念,它是对一项事物的抽象概括,可以包含该事物的一些属 ...
- 火狐 SSL 收到了一个弱临时 Diffie-Hellman 密钥的解决办法
连接 https网址 时发生错误. 在服务器密钥交换握手信息中 SSL 收到了一个弱临时 Diffie-Hellman 密钥. (错误码: ssl_error_weak_server_ephemera ...
- 【WebMisCentral WMC】基于Extjs 4.2x的企业级用户授权认证中心系统(SSO+AM+SM),多租户SAAS应用
http://saas.chinacloudtech.com 题记 三年磨一剑,在企业信息化的道路上已经走了3年之久了,3年多时间里做了很多,突破了很多:有无奈和辛酸,也有收货与喜悦:自我价值也在不断 ...
- jquery.pjax.js bug问题解决集锦
jquery.pjax 是一个很好的局部刷新插件,但实际应用过程是还是会有很多小问题,部分问题解决如下: 1.pjax 局部加载时候,IE 存在缓存问题,很容易理解,pjax是通过jquery的aja ...