1、CountDownLatch (关灯走人)
让一些线程堵塞直到另一个线程完成一系列操作后才被唤醒。CountDownLatch 主要有两个方法,当一个或多个线程调用 await 方法时,调用线程会被堵塞,其他线程调用 countDown 方法会将计数减一(调用 countDown 方法的线程不会堵塞),当计数其值变为零时,因调用 await 方法被堵塞的线程会被唤醒,继续执行。
假设我们有这么一个场景,教室里有班长和其他6个人在教室上自习,怎么保证班长等其他6个人都走出教室在把教室门给关掉。
public class CountDownLanchDemo {
public static void main(String[] args) {
for (int i = 0; i < 6; i++) {
new Thread(() -> {
System.out.println(Thread.currentThread().getName() + " 离开了教室...");
}, String.valueOf(i)).start();
}
System.out.println("班长把门给关了,离开了教室...");
}
}
此时输出:
0 离开了教室...
1 离开了教室...
2 离开了教室...
3 离开了教室...
班长把门给关了,离开了教室...
5 离开了教室...
4 离开了教室...
发现班长都没有等其他人理他教室就把门给关了,此时我们就可以使用 CountDownLatch 来控制.
public class CountDownLanchDemo {
public static void main(String[] args) throws InterruptedException {
CountDownLatch countDownLatch = new CountDownLatch(6);
for (int i = 0; i < 6; i++) {
new Thread(() -> {
countDownLatch.countDown();
System.out.println(Thread.currentThread().getName() + " 离开了教室...");
}, String.valueOf(i)).start();
}
countDownLatch.await();
System.out.println("班长把门给关了,离开了教室...");
}
}
此时输出:
0 离开了教室...
1 离开了教室...
2 离开了教室...
3 离开了教室...
4 离开了教室...
5 离开了教室...
班长把门给关了,离开了教室...
2、CyclicBarrier (满车出发)
我们假设有这么一个场景,每辆车只能坐个人,当车满了,就发车。
package com.example.rabbitmq.test.nio;
import java.util.concurrent.BrokenBarrierException;
import java.util.concurrent.CyclicBarrier;
public class cyclicBarrier {
public static void main(String[] args) {
//车上共十个座位
int is=10;
CyclicBarrier cyclicBarrier = new CyclicBarrier(is,()->{
System.out.println("满车出发!!");
});
for (int i = 0; i <is ; i++) {
new Thread(()->{
System.out.println(Thread.currentThread().getName()+"\t "+"上车");
try {
cyclicBarrier.await();
} catch (InterruptedException e) {
e.printStackTrace();
} catch (BrokenBarrierException e) {
e.printStackTrace();
}
},String.valueOf(i)).start();
}
}
}
执行结果:
1 上车
5 上车
4 上车
6 上车
3 上车
2 上车
0 上车
9 上车
8 上车
7 上车
满车出发!!
3、Semaphore
假设我们有 3 个停车位,6 辆车去抢
package com.example.rabbitmq.test.nio;
import java.util.concurrent.Semaphore;
public class SemaphoreDemo {
public static void main(String[] args) {
//假设停车场有三个车位
Semaphore semaphore = new Semaphore(3);
//留个车抢占车位
for (int i = 0; i <6 ; i++) {
new Thread(()->{
//停车入库
try {
semaphore.acquire();
System.out.println(Thread.currentThread().getName()+"\t "+"入库了...");
Thread.sleep(2000);
System.out.println(Thread.currentThread().getName()+"\t "+"出库了...");
} catch (InterruptedException e) {
e.printStackTrace();
}finally {
semaphore.release();
}
},String.valueOf(i)).start();
}
}
}
输出结果:
2 入库了...
0 入库了...
2 出库了...
1 出库了...
0 出库了...
3 入库了...
4 入库了...
5 入库了...
3 出库了...
5 出库了...
4 出库了...