系列九、JUC强大的辅助类
一、CountDownLatch
1.1、概述
让一些线程阻塞直到另一些线程完成一系列操作后才被唤醒
1.2、功能
CountDownLatch主要有两个方法,当一个或多个线程调用await方法时,这些线程会阻塞,其它线程调用countDown方法会将计数器减1(调用countDown方法的线程不会阻塞),当计数器的值变为0时,因await方法阻塞的线程会被唤醒,继续执行。
1.3、案例演示
/**
* @Author : 一叶浮萍归大海
* @Date: 2023/11/20 17:30
* @Description: CountDownLatch主要有两个方法,当一个或多个线程调用await方法时,这些线程会阻塞,
* 其它线程调用countDown方法会将计数器减1(调用countDown方法的线程不会阻塞),当计数器的值变为0时,因await方法阻塞的线程会被唤醒,继续执行。
* 需求:6个同学陆续离开教室后值班同学才可以关门
*/
public class CountDownLatchMainApp {
public static void main(String[] args) throws InterruptedException {
CountDownLatch countDownLatch = new CountDownLatch(6);
for (int i = 1; i <= 6; i++) {
new Thread(() -> {
try {
// 线程休眠(单位:毫秒)
try {
TimeUnit.MILLISECONDS.sleep(300);
} catch (Exception e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + "\t号同学离开教室!");
countDownLatch.countDown();
} catch (Exception e) {
e.printStackTrace();
}
}, String.valueOf(i)).start();
}
countDownLatch.await();
System.out.println(Thread.currentThread().getName() + "\t**************值班班长关门走人!");
}
}
二、CicyleBarrier
2.1、概述
CyclicBarrier的字面意思是可循环(Cyclic)使用的屏障(Barrier)。它要做的事情是,当一组线程到达一个屏障(也可以叫同步点)时被阻塞,直到最后一个线程到达屏障时,屏障才会开门,所有被屏障拦截的线程才会继续干活;
线程进入屏障通过CyclicBarrier的await()方法;
2.2、案例代码
/**
* @Author : 一叶浮萍归大海
* @Date: 2023/11/20 17:41
* @Description: 需求:集齐7颗龙珠就可以召唤神龙
* <p>
* constructor CyclicBarrier(int parties, Runnable barrierAction)
*/
public class CyclicBarrierMainApp {
private static final int NUMBER = 7;
public static void main(String[] args) {
CyclicBarrier cyclicBarrier = new CyclicBarrier(NUMBER, () -> {
System.out.println("*****集齐7颗龙珠就可以召唤神龙");
});
for (int i = 1; i <= 7; i++) {
new Thread(() -> {
System.out.println(Thread.currentThread().getName() + "\t 号七龙珠被收集!");
try {
cyclicBarrier.await();
} catch (Exception e) {
e.printStackTrace();
}
}, String.valueOf(i)).start();
}
}
}
三、Semaphore
3.1、概述
Semaphore的中文意思是信号量,主要功能有2个,即:
(1)用于多个共享资源的互斥使用;
(2)用于并发线程数的控制;
3.2、案例代码
/**
* @Author : 一叶浮萍归大海
* @Date: 2023/11/20 17:48
* @Description:
* 需求:一个停车场有三个车位,有6辆车来停车,只有当别的车停完车办完事情后才会空出车位
*/
public class SemaphoreMainApp {
public static void main(String[] args) {
// 模拟三个车位
Semaphore semaphore = new Semaphore(3);
for (int i = 1; i <= 6; i++) {
new Thread(() -> {
try {
/**
* 当一个线程调用acquire操作时,它要么成功获取信号量(信号量减1),要么一直等下去,直到有线程释放信号量或超时。
*/
semaphore.acquire();
System.out.println(Thread.currentThread().getName() + "\t号司机抢到了车位!");
// 线程休眠(单位:秒)
try { TimeUnit.SECONDS.sleep(new Random().nextInt(5)); } catch (Exception e) {e.printStackTrace();}
System.out.println(Thread.currentThread().getName() + "\t号司机办完事情,离开车位!");
} catch (Exception e) {
e.printStackTrace();
} finally {
// release(释放)实际上会将信号量的值加1,然后唤醒等待的线程。
semaphore.release();
}
}, String.valueOf(i)).start();
}
}
}