一、CountDownLatch
简介:CountDownLatch倒计时计数锁,其主要有俩个方法,当一个或多个线程调用await()方法时,这些线程会阻塞。
- 其他线程调用countDown()方法会将计数器减1(调用countDown方法的线程不会阻塞)
- 当计数器的值变为0时,因await()方法阻塞的线程会被唤醒,继续执行。
题目:用6个线程模拟6个同学,6个同学全部离开教室,班长线程关门。
public class CountDownLatchDemo {
public static void main(String[] args) throws InterruptedException {
CountDownLatch countDownLatch = new CountDownLatch(6); //倒计时计算器 初始值为6
for (int i = 1; i <= 6; i++) {
new Thread(()->{
System.out.println(Thread.currentThread().getName()+"位同学离开教室");
countDownLatch.countDown(); //初始值减1
},String.valueOf(i)).start();
}
countDownLatch.await(); //线程阻塞 countDownLatch初始值变为0才被唤醒
new Thread(()->{
System.out.println(Thread.currentThread().getName()+"关门");
},"班长").start();
}
}
1位同学离开教室
2位同学离开教室
3位同学离开教室
4位同学离开教室
6位同学离开教室
5位同学离开教室
班长关门
Process finished with exit code 0
main线程执行到countDownLatch.await(); 就会被阻塞,等到
countDownLatch的初始值变为0时才会被唤醒。
二、CyclicBarrier
简介:循环屏障,其实就是加法计算器,到达某个值时,执行某个线程。
题目:收集齐七颗龙族后,自动召唤神龙
public class CyclicBarrierDemo {
public static void main(String[] args) {
CyclicBarrier cyclicBarrier = new CyclicBarrier(7, () -> {
System.out.println("召唤神龙");
});
for (int i = 1; i <= 7; i++) {
final int temi = i;
new Thread(()->{
System.out.println("收集第:"+temi+"个龙珠");
try {
cyclicBarrier.await(); //等到7才会被唤醒
} catch (InterruptedException e) {
e.printStackTrace();
} catch (BrokenBarrierException e) {
e.printStackTrace();
}
},String.valueOf(i)).start();
}
}
}
解释:所有线程运行到cyclicBarrier.await()都会被阻塞,等到达7后执行cyclicBarrier中的召唤龙族线程,然后阻塞的线程才会被唤醒继续执行。
三、Semaphore信号量
Semaphore信号量作用:
- 常用于多个线程抢占多个资源
- 如果资源类为1,Semaphore等价于synchronized,多个线程抢占一个资源
在信号量上我们定义两种操作:
- acquire(获取):当一个线程调用acquire操作时,它要么通过成功获取信号量(信号量减1),要么一直等下去,直到有线程释放信号量,或超时。
- release(释放):实际上会将信号量的值加1,然后唤醒等待的线程
public class SemaphoreDemo {
public static void main(String[] args) {
Semaphore semaphore = new Semaphore(3); //3个资源类 假设是3个车位
for (int i = 1; i <= 6; i++) {
new Thread(()->{
try {
semaphore.acquire();
System.out.println(Thread.currentThread().getName()+":抢到了车位");
TimeUnit.SECONDS.sleep(3);
System.out.println(Thread.currentThread().getName()+":离开了车位");
} catch (InterruptedException e) {
e.printStackTrace();
}finally {
semaphore.release();
}
},String.valueOf(i)).start();
}
}
}
1:抢到了车位
3:抢到了车位
2:抢到了车位
2:离开了车位
1:离开了车位
4:抢到了车位
5:抢到了车位
3:离开了车位
6:抢到了车位
5:离开了车位
6:离开了车位
4:离开了车位
只要有线程离开车位就会有线程去抢车位。