简介
CountDownLatch底层也是由AQS,用来同步一个或多个任务的常用并发工具类,强制它们等待由其他任务执行的一组 *** 作完成。
CountDownLatch 是共享锁的一种实现,它默认构造 AQS 的 state 值为 count。当线程使用 countDown() 方法时,其实使用了tryReleaseShared方法以 CAS 的 *** 作来减少 state,直至 state 为 0 。当调用 await() 方法的时候,如果 state 不为 0,那就证明任务还没有执行完毕,await() 方法就会一直阻塞,也就是说 await() 方法之后的语句不会被执行。然后,CountDownLatch 会自旋 CAS 判断 state == 0,如果 state == 0 的话,就会释放所有等待的线程,await() 方法之后的语句得到执行。
作用
用来控制一个或者多个线程等待多个线程。CountDownLatch 允许 count 个线程阻塞在一个地方,直至所有线程的任务都执行完毕。
维护了一个计数器 cnt,每次调用 countDown() 方法会让计数器的值减 1,减到 0 的时候,那些因为调用 await() 方法而在等待的线程就会被唤醒。
public static void main(String[] args) { CountDownLatch cdl = new CountDownLatch(10); for (int i = 0; i <10 ; i++) { new Thread(()->{ System.out.println("同学"+Thread.currentThread().getName()+"上完晚自习走人"); cdl.countDown(); }).start(); } try { cdl.await(); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("班主任锁门走人"); } **** 同学Thread-0上完晚自习走人 同学Thread-3上完晚自习走人 同学Thread-2上完晚自习走人 同学Thread-4上完晚自习走人 同学Thread-1上完晚自习走人 同学Thread-5上完晚自习走人 班主任锁门走人CyclicBarrier详解
简介
用来控制多个线程互相等待,只有当多个线程都到达时,这些线程才会继续执行。
和 CountdownLatch 相似,都是通过维护计数器来实现的。线程执行 await() 方法之后计数器会减 1,并进行等待,直到计数器为 0,所有调用 await() 方法而在等待的线程才能继续执行。
对比
对于CountDownLatch,其他线程为游戏玩家,比如英雄联盟,主线程为控制游戏开始的线程。在所有的玩家都准备好之前,主线程是处于等待状态的,也就是游戏不能开始。当所有的玩家准备好之后,下一步的动作实施者为主线程,即开始游戏。对于CyclicBarrier,假设有一家公司要全体员工进行团建活动,活动内容为翻越三个障碍物,每一个人翻越障碍物所用的时间是不一样的。但是公司要求所有人在翻越当前障碍物之后再开始翻越下一个障碍物,也就是所有人翻越第一个障碍物之后,才开始翻越第二个,以此类推。类比地,每一个员工都是一个“其他线程”。当所有人都翻越的所有的障碍物之后,程序才结束。而主线程可能早就结束了,这里我们不用管主线程。
CyclicBarrier 和 CountdownLatch 的一个区别是,CyclicBarrier 的计数器通过调用 reset() 方法可以循环使用,所以它才叫做循环屏障。
public static void main(String[] args) { CyclicBarrier cyclicBarrier = new CyclicBarrier(7,()->{ System.out.println("召唤神龙*******");}); for (int i = 0; i < 7; i++) { final int tem=i; new Thread(()->{ System.out.println("超级赛亚人"+Thread.currentThread().getName()+"收集到了第"+tem+"颗龙珠"); try { cyclicBarrier.await(); } catch (InterruptedException e) { e.printStackTrace(); } catch (BrokenBarrierException e) { e.printStackTrace(); } },String.valueOf(i)).start(); } }Semaphore详解
Semaphore 类似于 *** 作系统中的信号量,可以限制对互斥资源的访问线程数。
public class SemPhoreDemo { public static void main(String[] args) { //设置3个车位 ,感觉有点类似线程池 Semaphore semaPhore = new Semaphore(3); for (int i = 0; i < 6; i++) { new Thread(()->{ try { semaPhore.acquire(); System.out.println(Thread.currentThread().getName()+"抢到车位"); Thread.sleep(1000); System.out.println(Thread.currentThread().getName()+"=====离开车位"); } catch (InterruptedException e) { e.printStackTrace(); }finally { semaPhore.release(); } },String.valueOf(i)).start(); } } }
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)