一.概念
1.CountDownLatch:计数器控制器,对初始化数量的递减直到0,允许继续运行。
2.CyclicBarrier:批量控制器,当数量到达设定值,统一执行。
3.Phaser:阶段控制器,分阶段执行逻辑,1阶段满足,2阶段才会开始。
4.Semaphore:信号控制器,信号数量控制,获取到信号的才可以执行。
5.Exchanger:只适用2个线程交换数据,基本用不到。
6.LockSupport:底层工具类,同步工具的阻塞原语。
二.使用
1.CountDownLatch:
public static void main(String[] args) {
//初始化数量5
System.out.println("主线程开始");
CountDownLatch countDownLatch = new CountDownLatch(5);
for (int i=0;i<5 ;i++){
new Thread(() -> {
//每个线程-1
countDownLatch.countDown();
System.out.println("当前计数:"+countDownLatch.getCount());
}).start();
}
try {
countDownLatch.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
//当计数为0 时 才会继续执行
System.out.println("主线程结束");
}
2.CyclicBarrier:
public static void main(String[] args) {
//初始化5个线程一批 满足5个打印已满装载,出发
CyclicBarrier cyclicBarrier = new CyclicBarrier(5,() -> {System.out.println("已满装载,出发");});
for (int i=0;i<12;i++){
new Thread(() ->{
try {
//等待满足5个,否则阻塞
cyclicBarrier.await();
//带等待时间的阻塞,超时抛出TimeoutException 和 BrokenBarrierException
//cyclicBarrier.await(5, TimeUnit.SECONDS);
} catch (InterruptedException e) {
e.printStackTrace();
} catch (BrokenBarrierException e) {
e.printStackTrace();
}
}).start();
}
}
3.Phaser:
public class PhaserTest {
//模拟5个人买彩票,1个人幸运儿中奖的情形
static PhaserDemo phaser = new PhaserDemo();
public static void main(String[] args) {
//注册监听5个线程
phaser.bulkRegister(5);
new ThreadDemo("小李").start();
new ThreadDemo("小张").start();
new ThreadDemo("小王").start();
new ThreadDemo("小华").start();
new ThreadDemo("幸运儿").start();
}
static class PhaserDemo extends Phaser{
@Override
//int phase表示流程编号(从0开始),int registeredParties表示这个流程需要多少人参与
protected boolean onAdvance(int phase, int registeredParties) {
//return false;进行下一阶段 return true;结束
switch (phase){
case 0 :
System.out.println("所有人都买了彩票" +registeredParties);
return false;
case 1 :
System.out.println("所有人等待开奖" +registeredParties);
return false;
case 2 :
System.out.println("幸运儿中奖" +registeredParties);
return true;
default:
return true;
}
}
}
//thread类
static class ThreadDemo extends Thread{
private String name;
ThreadDemo(String name){
this.name = name;
}
void buy(){
System.out.println(this.name+"买了彩票");
//到达阶段等待执行
phaser.arriveAndAwaitAdvance();
}
void waitting(){
System.out.println(this.name+"等待开奖");
//到达阶段等待执行
phaser.arriveAndAwaitAdvance();
}
void open(){
if(this.name.equals("幸运儿")){
System.out.println(this.name+"中奖");
//到达阶段等待执行
phaser.arriveAndAwaitAdvance();
}else{
//到达阶段取消执行
phaser.arriveAndDeregister();
}
}
@Override
public void run() {
//所有人买
buy();
//所有人等待
waitting();
//幸运儿留下
open();
}
}
}
4.Semaphore:
public static void main(String[] args) {
//注册两个信号,获取到信号的才可以执行
Semaphore semaphore = new Semaphore(2);
for (int i=0; i<5;i++){
new Thread(() ->{
try {
//尝试获取信号 返回是否获取到
//semaphore.tryAcquire()
//获取信号 获取不到阻塞
semaphore.acquire();
System.out.println(Thread.currentThread().getName()+"获取信号");
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
//释放信号
semaphore.release();
System.out.println(Thread.currentThread().getName()+"释放信号");
},"线程"+i).start();
}
}
5.Exchanger:
public static void main(String[] args) {
Exchanger<String> exchanger = new Exchanger<>();
new Thread(() -> {
String temp = "线程A变量";
try {
temp = exchanger.exchange(temp);
System.out.println(Thread.currentThread().getName()+temp);
} catch (InterruptedException e) {
e.printStackTrace();
}
},"线程A").start();
new Thread(() -> {
String temp = "线程B变量";
try {
temp = exchanger.exchange(temp);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName()+temp);
},"线程B").start();
}
6.LockSupport:
public static void main(String[] args) {
Thread thread = new Thread(() -> {
System.out.println("线程开始");
for (int i = 0; i < 10 ; i++) {
if(i == 5){
System.out.println("线程阻塞");
//使当前线程阻塞
LockSupport.park();
}
System.out.println("线程执行"+i);
}
});
thread.start();
long start = System.currentTimeMillis();
long end = System.currentTimeMillis();
//等待时间超过5s,打断t2线程。
while (end-start<5000){
end = System.currentTimeMillis();
}
//五秒后 唤醒入参线程
LockSupport.unpark(thread);
}
三、比较和场景
1.CountDownLatch:减为0后不可复用。
场景:确保一个计算不会执行,直到所需要的资源被初始化。
2.CyclicBarrier:可重复使用,当数量到达设定值,统一执行。
场景:约朋友们到某个餐厅一起吃饭,有些朋友可能会早到,有些朋友可能会晚到,但是当所有朋友到齐才会开餐。
3.Phaser:阶段性控制,可在过程中添加监视数量。
场景:分阶段执行的业务,某些阶段不允许某些条件进入。
4.Semaphore:可以定义为公平控制器,默认非公平,具有尝试获取信号功能,可自定义获取信号数量和释放数量,需要手动释放信号。
场景:银行窗口并发服务只有几个。
5.Exchanger:仅限俩个线程交换数据,了解即可。
6.LockSupport:同步工具的底层原语,如AQS。