允许一个或多个线程等待直到其他线程中执行的一组操作完成同步辅助
计数器
public class CountDownLatchDemo { public static void main(String[] args) throws InterruptedException { //总数是6,必须要执行任务的时候,再执行! CountDownLatch countDownLatch = new CountDownLatch(6); for (int i = 0; i <= 6 ; i++) { new Thread(()->{ System.out.println(Thread.currentThread().getName()+"get out"); countDownLatch.countDown();// 计数器-1 },String.valueOf(i)).start(); } countDownLatch.await();//等待计数器归零,然后再向下执行,需要抛出异常 System.out.println("close door"); } }
原理:
countDownLatch.countDown();// 计数器-1
countDownLatch.await();//等待计数器归零,然后再向下执行
每次有线程调用countDownLatch.countDown();// 计数器-1
,调用这个方法不会阻塞,假设计数器变为0,countDownLatch.await();
就会被唤醒,继续执行
允许一组线程全部等待彼此达到共同屏障点,同步辅助
加法计数器
public class CyclicBarrierDemo { public static void main(String[] args) { //集齐7颗龙珠召唤神龙 //召唤龙珠的线程 CyclicBarrier cyclicBarrier = new CyclicBarrier(7,()->{ System.out.println("召唤神龙成功"); }); for (int i = 0; i <= 7; i++) { //加final,变量会存在堆中的方法区里, //子线程共享进程的堆,所以能读到。否则会存在另一个线程的栈中,不同线程读不到 final int temp = i; new Thread(()->{ System.out.println(Thread.currentThread().getName()+"收集了"+temp); try { //通过await来计数,await之后本次线程会被阻塞, // 直到神龙召唤后,才执行后面的 cyclicBarrier.await(); } catch (InterruptedException e) { e.printStackTrace(); } catch (BrokenBarrierException e) { e.printStackTrace(); } }).start(); } } }
一个计数信号量,在概念上,信号量维持一组许可证。如果有必要,每个acquire()都会阻塞,直到许可证可用,然后才能使用它
6个车 ----> 3个停车位
public class SemaphoreDemo { public static void main(String[] args) { //线程数量:停车位 限流 Semaphore semaphore = new Semaphore(3); for (int i = 0; i <= 6; i++) { new Thread(()->{ //acquire() 得到 try { semaphore.acquire(); System.out.println(Thread.currentThread().getName() + "抢到车位"); TimeUnit.SECONDS.sleep(3); System.out.println(Thread.currentThread().getName() + "离开"); } catch (InterruptedException e) { e.printStackTrace(); }finally { //release() 释放 semaphore.release(); } },String.valueOf(i)).start(); } } }
原理:
semaphore.acquire();
得到,假如已经满了,等待,等待被释放为止
semaphore.release();
释放,会将当前的信号量 +1 然后唤醒等待的线程
作用:多个共享资源互斥的使用! 并发限流,控制最大的线程数