sync同步器框架
CountDownLatch/CyclicBarrier/Semaphore使用过吗?
CountDownLatch(倒数计数器)
-
概念:让一些线程阻塞直到另一些线程完成一系列操作才被唤醒
-
来自:
-
主要方法:
- await:当一个或多个线程调用await方法时,调用线程会被阻塞。
- countDown:会将计数器-1
public class CountDownLatchDemo {
public static void main(String[] args)throws Exception{
CountDownLatch countDownLatch = new CountDownLatch(6);
for(int i = 0; i <= 6; i++){
final int tempInt = i;
new Thread(() -> {
System.out.println(Thread.currentThread().getName()+"\t上完自习,离开教室");
countDownLatch.countDown();
}, String.valueOf(i)).start();
}
countDownLatch.await();
System.out.println(Thread.currentThread().getName()+"\t*******班长最后关门走人");
}
CountDownLatch 和 join 方法的区别
-
调用一个子线程的join()方法后,该线程会一直被阻塞直到子线程运行完毕
而,CountDownLatch则使用计数器来允许子线程运行完毕,或者在运行中增减计数
-
使用线程池来管理线程时一般都是直接添加Runnable 到线程池,这时候就没办法调用线程的join()方法了
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 tempInt = i;
new Thread(() ->{
System.out.println(Thread.currentThread().getName()+"\t 收集到第:"+tempInt+"颗龙珠");
try{
cyclicBarrier.await();
}catch (InterruptedException e){
e.printStackTrace();
}catch (BrokenBarrierException e){
e.printStackTrace();
}
},String.valueOf(i)).start();
}
}
}
Semaphore(信号量)
允许多个线程同时访问
可公平,非公平构造
- 目的:
- 一个是用于共享资源的互斥使用
- 另一个用于并发线程数的控制
//模拟抢车位
public class SemaphoreDemo {
public static void main(String[] args){
//3个车位
Semaphore semaphore = new Semaphore(3);
//6辆车抢
for(int i = 1;i <= 6; i++){
new Thread(() ->{
try{
//抢车位
semaphore.acquire();
System.out.println(Thread.currentThread().getName()+"\t抢到车位");
//停2s
try{
TimeUnit.SECONDS.sleep(2);
}catch (InterruptedException e){
e.printStackTrace();
}
}catch (InterruptedException e){
e.printStackTrace();
}finally{
System.out.println(Thread.currentThread().getName()+"\t离开车位");
//释放车位
semaphore.release();
}
},String.valueOf(i)).start();
}
}
}