CountDownLatch
让一些线程阻塞直到另外一些完成后才被唤醒。
CountDownLatch 主要有两个方法,当一个或多个线程调用 await
方法时,调用线程会被阻塞.其他线程调用 countDown 方法计数器减1(调用 countDown 方法时线程不会阻塞),当计数器的值变为0,因调用await方法被阻塞的线程会被唤醒,继续执行。
public class CountDownLatchDemo {
public static void main(String[] args) throws InterruptedException {
CountDownLatch countDownLatch = new CountDownLatch(6);
for(int i = 0;i< 6 ;i++){
new Thread(()->{
System.out.println(Thread.currentThread().getName()+"\t AAAAAAAAAA");
countDownLatch.countDown();
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
},i+"").start();
}
countDownLatch.await();
System.out.println(Thread.currentThread().getName()+"\t BBBBBBBBBBBBBB \t" + countDownLatch.getCount());
}
}
0 AAAAAAAAAA
3 AAAAAAAAAA
2 AAAAAAAAAA
5 AAAAAAAAAA
1 AAAAAAAAAA
4 AAAAAAAAAA
main BBBBBBBBBBBBBB 0
main 线程由于 await 处于阻塞状态,等待 countDownLatch 归零后才开始执行。
CyclicBarrier
CyclicBarrier 的字面意思是可循环(Cyclic) 使用的屏障(barrier)。它要做的事情是:让一组线程到达一个屏障(也可以叫做同步点)时被阻塞,直到最后一个线程到达屏障时,屏障才会开门,所有被屏障拦截的线程才会继续干活,线程进入屏障通过 CyclicBarrier 的 await() 方法。
public class CyclicBarrierDemo {
public static void main(String[] args) {
CyclicBarrier cyclicBarrier = new CyclicBarrier(7,()->{
System.out.println("召唤神龙");
});
for (int i = 0; i < 7; i++) {
final int tmpInt = i;
new Thread(()->{
System.out.println(Thread.currentThread().getName()+"\t"+tmpInt);
try {
cyclicBarrier.await();
} catch (InterruptedException e) {
e.printStackTrace();
} catch (BrokenBarrierException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName()+"\t完成");
},i+" 线程").start();
}
}
}
0 线程 0
3 线程 3
2 线程 2
1 线程 1
6 线程 6
5 线程 5
4 线程 4 # 直到 cyclicBarrier 之上的代码循环遍历完成,才进行执行下一行代码
召唤神龙
4 线程 完成
0 线程 完成
2 线程 完成
5 线程 完成
3 线程 完成
6 线程 完成
1 线程 完成
CyclicBarrier 的 await 等待其他线程执行,直到其他线程完成,当前线程才继续执行。
Semaphore
Semaphore信号量主要有两个目的:
- 用于多个共享资源的互斥使用;
- 用于并发数量的控制(是synchronized的加强版,当并发数量为1时就退化成synchronized);
主要方法:
- Semaphore(int permits):构造函数,允许控制的并发数量;
- acquire():请求一个信号量,导致信号量的数量减1;
- release():释放一个信号量,信号量加1;
public class SemaphoreDemo {
public static void main(String[] args) {
Semaphore semaphore = new Semaphore(5);
for (int i = 1; i <= 1000; i++) {
new Thread(()->{
try {
semaphore.acquire();
System.out.println(Thread.currentThread().getName() + "\t抢到车位");
try {
TimeUnit.SECONDS.sleep(3);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + "\t停车3秒后离开车位");
}catch (Exception e){
e.printStackTrace();
}finally {
semaphore.release();
}
},String.valueOf(i)).start();
}
}
}
1 抢到车位
2 抢到车位
4 抢到车位
3 抢到车位
5 抢到车位
5 停车3秒后离开车位
4 停车3秒后离开车位
1 停车3秒后离开车位
2 停车3秒后离开车位
3 停车3秒后离开车位