CountDownLatch、Semaphore和CyclicBarrier的学习
JAVA并发包中有三个类用于同步一批线程的行为,分别是CountDownLatch、Semaphore和CyclicBarrier。
-
CountDownLatch
CountDownLatch是一个计数器闭锁,主要的功能就是通过await()方法来阻塞住当前线程,然后等待计数器减少到0了,再唤起这些线程继续执行。 这个类里主要有两个方法,一个是向下减计数器的方法:countdown()
import java.util.concurrent.CountDownLatch;
/**
* @Auther: huanglong
* @Date: 2019/1/3 16:30
* @Description:
*/
public class TestCountDownLatch {
public static void main(String[] args) throws InterruptedException {
final CountDownLatch begin = new CountDownLatch(1);
final CountDownLatch end = new CountDownLatch(10);
for (int i = 0 ;i < 10;i++ ){
new Thread(new Player(begin,end),"player" + i).start();
}
System.out.println("Game Start");
begin.countDown();
end.await();
System.out.print("Game Over");
}
}
class Player implements Runnable{
// 开始的倒数锁
private final CountDownLatch begin ;
// 结束的倒数锁
private final CountDownLatch end;
Player(CountDownLatch begin, CountDownLatch end) {
this.begin = begin;
this.end = end;
}
@Override
public void run() {
try {
// 如果当前计数为零,则此方法立即返回。
// 等待
begin.await();
Thread.sleep((long) (Math.random() * 10000));
System.out.println(Thread.currentThread().getName() + " arrived");
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
// 每个选手到达终点时,end就减一
end.countDown();
}
}
}
测试结果为
Game Start
player8 arrived
player1 arrived
player6 arrived
player7 arrived
player2 arrived
player9 arrived
player5 arrived
player0 arrived
player3 arrived
player4 arrived
Game Over
CountDownLatch是一个同步的辅助类,允许一个或多个线程,等待其他一组线程完成操作,再继续执行。
个人理解:CountDownLatch 可以理解为倒计时计数,比如多个游戏参与者,每个游戏参与者的角色死亡之后 ,游戏才算结束。
-
Semaphore
Semaphore与CountDownLatch相似,不同的地方在于Semaphore的值被获取到后是可以释放的,并不像CountDownLatch那样一直减到底。它也被更多地用来限制流量,类似阀门的 功能。如果限定某些资源最多有N个线程可以访问,那么超过N个主不允许再有线程来访问,同时当现有线程结束后,就会释放,然后允许新的线程进来。
import java.util.concurrent.Semaphore;
/**
* @Auther: huanglong
* @Date: 2019/1/3 16:30
* @Description:
*/
public class TestSemaphore {
public static void main(String[] args) throws InterruptedException {
//允许并行最大线程数
final Semaphore max = new Semaphore(5,true);
System.out.println("Test Start\n");
for (int i = 0 ;i < 10;i++ ){
new Thread(new Reader(max),"Reader" + i).start();
}
}
}
class Reader implements Runnable{
//
private final Semaphore max ;
Reader(Semaphore max) {
this.max = max;
}
@Override
public void run() {
try {
//获取资源执行
max.acquire();
System.out.println(Thread.currentThread().getName() + " --in Room");
Thread.sleep((long) (Math.random() * 10000));
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
//执行完毕释放资源
max.release();
System.out.println(Thread.currentThread().getName() + " --leave Room");
}
}
}
结果:
Test Start
Reader2 --in Room
Reader6 --in Room
Reader1 --in Room
Reader5 --in Room
Reader9 --in Room
Reader1 --leave Room
Reader0 --in Room
Reader2 --leave Room
Reader4 --in Room
Reader6 --leave Room
Reader8 --in Room
Reader5 --leave Room
Reader3 --in Room
Reader3 --leave Room
Reader7 --in Room
Reader0 --leave Room
Reader9 --leave Room
Reader7 --leave Room
Reader4 --leave Room
Reader8 --leave Room
个人理解:跟 CountDownLatch 类似,但计数可以可以重置,类似游乐园,有最大容量限制,到达最大容量限制,就不允许进入了。
-
CyclicBarrier
CyclicBarrier是用来一个关卡来阻挡住所有线程,等所有线程全部执行到关卡处时,再统一执行下一步操作,它里面最重要的方法是await()方法
import java.util.concurrent.BrokenBarrierException;
import java.util.concurrent.CyclicBarrier;
import java.util.concurrent.Semaphore;
/**
* @Auther: huanglong
* @Date: 2019/1/3 16:30
* @Description:
*/
public class TestCyclicBarrier {
public static void main(String[] args) throws InterruptedException {
final CyclicBarrier barrier = new CyclicBarrier(5, new Runnable() {
@Override
public void run() {
System.out.println("所有工作完成!");
}
});
System.out.println("Test Start\n");
for (int i = 0 ;i < 5;i++ ){
new Thread(new Tool(barrier),"Tool" + i).start();
}
}
}
class Tool implements Runnable{
private final CyclicBarrier condition ;
Tool(CyclicBarrier condition) {
this.condition = condition;
}
@Override
public void run() {
try {
System.out.println(Thread.currentThread().getName() + " 工作完成!");
condition.await();
Thread.sleep((long) (Math.random() * 10000));
} catch (InterruptedException e) {
e.printStackTrace();
} catch (BrokenBarrierException e) {
e.printStackTrace();
}
}
}
执行结果
Test Start
Tool0 工作完成!
Tool1 工作完成!
Tool4 工作完成!
Tool3 工作完成!
Tool2 工作完成!
所有工作完成!
个人理解:比如车辆制造,有很多模块可以同时制造,但是有的模块简单速度快,建造完毕后仍然等待其他模块一起完成才能组装成一辆车。
以上只是初步理解,具体细节以后探讨,做此记录,防止忘记
参考其他资料
https://blog.csdn.net/yanhandle/article/details/9016329
https://blog.csdn.net/chenchaofuck1/article/details/51596786