Java并发包下为我们提供了一些辅助工具类,来简单看看如何使用
一、CountDownLatch
减法器,必须等到减法器的值为0了,才能继续往下执行。也可以将它理解为栅栏
让一些线程堵塞直到另一个线程完成一系列操作后才被唤醒。CountDownLatch 主要有两个方法,当一个或多个线程调用 await 方法时,调用线程会被堵塞,其他线程调用 countDown 方法会将计数减一(调用 countDown 方法的线程不会堵塞),当计数其值变为零时,因调用 await 方法被堵塞的线程会被唤醒,继续执行。
来看两个小案例,模拟六个学生全部走出教室门之后才关门
public class CountDownLatchDemo {
public static void main(String[] args) throws InterruptedException {
CountDownLatch countDownLatch=new CountDownLatch(6);
for(int i=1;i<=6;i++){
new Thread(()->{
System.out.println(Thread.currentThread().getName()+"Go out");
countDownLatch.countDown(); //数量减一
},String.valueOf(i)).start();
}
countDownLatch.await();
System.out.println("Close Door");
}
}
再来看看一个刘关张三结义的案例
/**
* Author: 徐志
* Date: 2020/8/8 16:44
*/
public class CountDownLatchDemo2 {
public static void main(String[] args) {
CountDownLatch countDownLatch=new CountDownLatch(2);
new Thread(()->{
System.out.println("刘备--》在等待");
try {
countDownLatch.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("刘关张桃园三结义");
}).start();
new Thread(()->{
System.out.println("张飞--》骑马而来");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("张飞拜见大哥");
countDownLatch.countDown();
}).start();
new Thread(()->{
System.out.println("关羽--》骑马而来");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("关羽拜见大哥");
countDownLatch.countDown();
}).start();
}
}
必须三位壮士到齐了,才能三结义。
有时候在程序里,我们需要保证,让某一部分代码执行完成后,主线程才继续往下执行,就可以使用CountDownLatch
二、CyclicBarrier
这是一个加法器,和CountDownLatch正好相反,必须数量达到我们设定的值之后,才会执行相应的代码
每调用一次await()方法,计数器加1
public class CyclicBarrierDemo {
public static void main(String[] args) throws BrokenBarrierException, InterruptedException {
CyclicBarrier cyclicBarrier=new CyclicBarrier(8,()->{
System.out.println("召唤神龙成功");
});
for (int i = 1; i <=7 ; i++) {
final int temp=i;
new Thread(()->{
System.out.println(Thread.currentThread().getName()+"收集"+temp+"个龙珠");
try {
cyclicBarrier.await();
} catch (InterruptedException e) {
e.printStackTrace();
} catch (BrokenBarrierException e) {
e.printStackTrace();
}
}).start();
}
cyclicBarrier.await();
System.out.println("悟空和他的小伙伴过上了幸福的生活");
}
}
三、信号量
信号量主要用于两个目的,一个是用于多个共享资源的互斥使用,另一个用于并发线程数的控制。
举例说明就是抢车位,车位只有3个,而车有六个,必须等停在车位上的车走了,等待的车才能进入
public class SemaphoreTest {
public static void main(String[] args) {
Semaphore semaphore=new Semaphore(3); //限流
for(int i=1;i<=6;i++){
new Thread(()->{
try {
semaphore.acquire();
System.out.println(Thread.currentThread().getName()+"抢到车位");
TimeUnit.SECONDS.sleep(2);
System.out.println(Thread.currentThread().getName()+"离开车位");
} catch (InterruptedException e) {
e.printStackTrace();
}finally {
semaphore.release();
}
}).start();
}
}
}