1:CountDown(减少计数)
让一些线程阻塞直到另一些线程完成一系列操作后才被唤醒。
/**
*
* @Description:
* *让一些线程阻塞直到另一些线程完成一系列操作后才被唤醒。
*
* CountDownLatch主要有两个方法,当一个或多个线程调用await方法时,这些线程会阻塞。
* 其它线程调用countDown方法会将计数器减1(调用countDown方法的线程不会阻塞),
* 当计数器的值变为0时,因await方法阻塞的线程会被唤醒,继续执行。
*
* 解释:6个同学陆续离开教室后值班同学才可以关门。
*
* main主线程必须要等前面6个线程完成全部工作后,自己才能开干
* @author Lrc
*/
public class CountDownDemo {
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()+"\t已离开");
countDownLatch.countDown();
}, CountryEnum.forEach_CountryEnum(i).getMessage()).start();
}
countDownLatch.await();
System.out.println(Thread.currentThread().getName()+"\t秦走了");
}
}
齐 已离开
赵 已离开
燕 已离开
韩 已离开
楚 已离开
魏 已离开
main 秦走了
上面的例子可以看到,如果这六个同学都没有离开,主线程一致在堵塞,知道离开后开始执行下面的语句
使用方法:
- 初始化设置计数器
- 其它线程调用countDown方法会将计数器减1(调用countDown方法的线程不会阻塞),
- 当计数器的值变为0时,因await方法阻塞的线程会被唤醒,继续执行。
1:CyclicBarrier(循环栅栏)
- CyclicBarrier
- 的字面意思是可循环(Cyclic)使用的屏障(Barrier)。它要做的事情是,
- 让一组线程到达一个屏障(也可以叫同步点)时被阻塞,
- 直到最后一个线程到达屏障时,屏障才会开门,所有
- 被屏障拦截的线程才会继续干活。
- 线程进入屏障通过CyclicBarrier的await()方法。
构造器可以看到,需要传入一个Runnable
/**
* 让一组线程到达一个屏障(也可以叫同步点)时被阻塞,
* 直到最后一个线程到达屏障时,屏障才会开门,所有
* 被屏障拦截的线程才会继续干活。
* 线程进入屏障通过CyclicBarrier的await()方法。
* 集齐七颗龙珠就可以召唤神龙
*
* @Author:LRC
* @Date:10:45 上午 2020/7/5
*/
public class CyclicBarrierDemo {
public static void main(String[] args) {
CyclicBarrier cyclicBarrier = new CyclicBarrier(7, () -> {
//集齐七个之后需要做的时期
System.out.println("已集齐,召唤神龙");
});
for (int i = 1; i <= 7; i++) {
new Thread(()->{
try {
System.out.println(Thread.currentThread().getName()+"\t收集到了");
cyclicBarrier.await();
} catch (InterruptedException e) {
e.printStackTrace();
} catch (BrokenBarrierException e) {
e.printStackTrace();
}
},String.valueOf(i)).start();
}
}
}
1 收集到了
4 收集到了
3 收集到了
2 收集到了
6 收集到了
5 收集到了
7 收集到了
已集齐,召唤神龙
进程已结束,退出代码 0
这个辅助类就是,设置一个屏障,直到最后一个线程到达后,这个屏障才会开门
3:Semaphore(信号灯)
信号量主要用于两个目的,一个是用于多个共享资源的互斥使用,另一个用于并发线程数的控制。
在信号量上我们定义两种操作:
- acquire(获取) 当一个线程调用acquire操作时,它要么通过成功获取信号量(信号量减1),
-
要么一直等下去,直到有线程释放信号量,或超时。
- release(释放)实际上会将信号量的值加1,然后唤醒等待的线程。
public class SemaphoreDemo {
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()+"\t 号车进入停车位");
TimeUnit.SECONDS.sleep(3);
System.out.println(Thread.currentThread().getName()+"\t号车离开停车位");
} catch (InterruptedException e) {
e.printStackTrace();
}finally {
//释放资源
semaphore.release();
}
},String.valueOf(i)).start();
}
}
}
1 号车进入停车位
3 号车进入停车位
2 号车进入停车位
2 号车离开停车位
3 号车离开停车位
1 号车离开停车位
4 号车进入停车位
6 号车进入停车位
5 号车进入停车位
4 号车离开停车位
5 号车离开停车位
6 号车离开停车位