1,CyclicBarrier
屏障:当线程Ta先执行到了await方法时候,等待;然后Tb又执行到了await方法,继续等待,直到最后一个线程执行到了他自己的await方法之后,图中的三个线程才会继续一块走下去,当传入barrierAction时,所有线程执行完await方法后,会执行barrierAction进行汇总,汇总结束后执行await方法的线程才会继续运行
屏障可以多次使用,await可以反复调用
CyclicBarrier构造方法传入的数字必须和执行任务的线程数量一致
与countDownLatch的区别:
1,CyclicBarrier计数器可以多次使用,同时计数器可以使用reset()方法重置,countDownLatch只能调用一次
2,CyclicBarrier工作线程本身之间相互协调,countDownLatch是利用外部的线程来协调执行
3,CyclicBarrier的计数器必须等于线程数,countDownLatch的控制计数器和线程大小没有必然关系
4,CyclicBarrier可以进行汇总,只需传入barrierAction, countDownLatch执行的时候,不能进行其他的操作,比如汇总计算结果
代码示例
public class CyclicBarrierTest {
// 自定义工作线程
private static class Worker extends Thread {
private CyclicBarrier cyclicBarrier;
public Worker(CyclicBarrier cyclicBarrier) {
this.cyclicBarrier = cyclicBarrier;
}
@Override
public void run() {
super.run();
try {
System.out.println(Thread.currentThread().getName() + "开始等待其他线程");
cyclicBarrier.await();
System.out.println(Thread.currentThread().getName() + "开始执行");
// 工作线程开始处理,这里用Thread.sleep()来模拟业务处理
Thread.sleep(1000);
System.out.println(Thread.currentThread().getName() + "执行完毕");
} catch (Exception e) {
e.printStackTrace();
}
}
}
public static void main(String[] args) {
int threadCount = 3;
CyclicBarrier cyclicBarrier = new CyclicBarrier(threadCount);
for (int i = 0; i < threadCount; i++) {
System.out.println("创建工作线程" + i);
Worker worker = new Worker(cyclicBarrier);
worker.start();
}
}
}
2,Semaphore
主要做流量控制,协调各个现程,合理利用资源,源码基于AQS实现
场景:数据库连接池,控制某一时刻只有一定数量的连接
使用:创建对象,传入最大同时进行的任务数量,使用时先调用acquirs方法获取‘许可证’,等工作完成之后再调用release方法放回许可证供其他线程使用
注意事项:虽然事先定义了许可证的数量,但是如果不调用acquirs方法,直接调用release方法是允许的,许可证数量也会增加相应数量,会导致许可证数量远大于设定的数量从而导致控流失效
3,Exchange
两个线程之间,对同一类型的数据进行操作,当线程a先执行完,调用exchange方法时等待b线程的执行;线程b的执行完,调用exchange方法时,因为线程a已经等着,此时两个线程进行数据交换,a的数据交给b,b的数据交给a,然后再互相继续执行,数据交换过程线程安全,只支持两个线程

