【JUC】CyclicBarrier和Semaphore的使用
CyclicBarrier的使用
CyclicBarrier:可以让一组检测到一个屏障时被阻塞,直到最后一个线程到达屏障时,屏障才会开门,所有的屏障拦截的线程才会继续执行,线程进入屏障通过CyclicBarrier的wait方法。
public class CyclicBarrierTest { public static void main(String[] args) { CyclicBarrier cyclicBarrier = new CyclicBarrier(5,()->{ System.out.println("五个线程都到了,一起输出"); }); for (int i = 0; i < 5; i++) { //这里如果不用final修饰,那么主线程结束的时候某个其他线程还在等待 // 但是tmp的生命周期已经结束,为了避免这种情况发生,要用final修饰 final int tmp = i; new Thread(()->{ System.out.println(Thread.currentThread().getName()+ "-线程到了:" + tmp); try { cyclicBarrier.await(); } catch (InterruptedException e) { e.printStackTrace(); } catch (BrokenBarrierException e) { e.printStackTrace(); } },String.valueOf(i)).start(); } } }
输出结果
0-线程到了:0
4-线程到了:4
2-线程到了:2
1-线程到了:1
3-线程到了:3
五个线程都到了,一起输出
Semaphore的使用
Semaphore可以替代synchronizated(信号量设为1)和Lock
信号量的两个作用:1. 多个共享资源的互斥使用 2. 并发线程数的控制
第一个构造方法默认非公平锁
非公平锁:一上来就抢占资源,允许线程加塞。在高并发的情况下,可能会造成优先级反转或饥饿现象。它会直接尝试占有锁,尝试失败的话再采用公平锁的方式。非公平锁的优点是吞吐量大。
公平锁:多个线程按照申请锁的顺序来获取,先来先得。
1 import java.util.concurrent.Semaphore; 2 import java.util.concurrent.TimeUnit; 3 4 /** 5 * 多对多的抢占资源 6 */ 7 public class SemaphoreDemo { 8 public static void main(String[] args) { 9 //3个停车位 10 Semaphore position = new Semaphore(3); 11 //6辆车想要停车 12 for (int i = 0; i < 6; i++) { 13 new Thread(()->{ 14 try { 15 position.acquire();//抢到一张门票 16 System.out.println("张"+Thread.currentThread().getName()+":我抢到车位了!"); 17 TimeUnit.SECONDS.sleep(1);//保安维持秩序 等待下一轮抢票 18 System.out.println("张"+Thread.currentThread().getName()+":我走了!"); 19 } catch (InterruptedException e) { 20 e.printStackTrace(); 21 } finally { 22 position.release();//释放车位 23 } 24 },String.valueOf(i)).start(); 25 } 26 } 27 }
输出结果:
张0:我抢到车位了!
张2:我抢到车位了!
张1:我抢到车位了!
张0:我走了!
张1:我走了!
张3:我抢到车位了!
张2:我走了!
张4:我抢到车位了!
张5:我抢到车位了!
张5:我走了!
张3:我走了!
张4:我走了!