
一、CountDownLatch作用计数器主要方法await使当前线程进入同步队列进行等待直到latch的值被减到0或者当前线程被中断当前线程就会被唤醒。countDown使latch的值减1如果减到了0则会唤醒所有等待在这个latch上的线程。1.1 CountDownLatch简单应用CountDownExample.javapackage cn.zxj.util;importjava.util.concurrent.CountDownLatch;public class CountDownExample{//接收一个int型参数表示要等待的工作线程的个数 static CountDownLatchcountDownLatchnew CountDownLatch(1);static class Thread1 extends Thread{Override public voidrun(){//TODO try{Thread.sleep(500);countDownLatch.await();}catch(InterruptedException e){e.printStackTrace();}System.out.println(Thread.currentThread().getName()执行结束);//表示我已经干完了}}static class Thread2 extends Thread{Override public voidrun(){try{Thread.sleep(500);countDownLatch.await();}catch(InterruptedException e){e.printStackTrace();}System.out.println(Thread.currentThread().getName()执行结束);}}static class Thread3 extends Thread{Override public voidrun(){try{Thread.sleep(500);countDownLatch.await();}catch(InterruptedException e){e.printStackTrace();}System.out.println(Thread.currentThread().getName()执行结束);}}public static void main(String[]args)throws InterruptedException{Thread1t1new Thread1();t1.start();Thread2t2new Thread2();t2.start();Thread3t3new Thread3();t3.start();System.out.println(主线程执行结束);countDownLatch.countDown();}}1.2 CountDownLatch的业务应用在启动应用的时候去对第三方的应用做健康检测BaseHealthChecker.javapackage cn.zxj.util;public abstract class BaseHealthChecker implements Runnable{private String serviceName;//服务名称 private boolean serviceUp;public BaseHealthChecker(String serviceName){this.serviceNameserviceName;}Override public voidrun(){try{verifyService();serviceUptrue;}catch(Exception e){serviceUpfalse;}finally{}}/** * 检查服务的健康情况 */ public abstract void verifyService()throws Exception;public StringgetServiceName(){returnserviceName;}public booleanisServiceUp(){returnserviceUp;}}CacheHealthChecker.javapackage cn.zxj.util;importjava.util.concurrent.CountDownLatch;public class CacheHealthChecker extends BaseHealthChecker{private CountDownLatch countDownLatch;public CacheHealthChecker(CountDownLatch countDownLatch){super(CacheHealthChecker);this.countDownLatchcountDownLatch;}Override public void verifyService()throws Exception{System.out.println(Checking:this.getServiceName());try{Thread.sleep(1000);// 如果检查失败throw RuntimeException()}catch(Exception e){throw e;}countDownLatch.countDown();System.out.println(this.getServiceName() 健康状态正常);}}DatabaseHealthChecker.javapackage cn.zxj.util;importjava.util.concurrent.CountDownLatch;public class DatabaseHealthChecker extends BaseHealthChecker{private CountDownLatch countDownLatch;public DatabaseHealthChecker(CountDownLatch countDownLatch){super(DatabaseHealthChecker);this.countDownLatchcountDownLatch;}Override public void verifyService()throws Exception{System.out.println(Checking:this.getServiceName());try{Thread.sleep(1000);}catch(Exception e){throw e;}countDownLatch.countDown();System.out.println(this.getServiceName() 健康状态正常);}}ApplicationStartup.javapackage cn.zxj.util;importjava.util.ArrayList;importjava.util.List;importjava.util.concurrent.CountDownLatch;public class ApplicationStartup{private static ListBaseHealthCheckerservices;private static CountDownLatchcountDownLatchnew CountDownLatch(2);static{servicesnew ArrayList();services.add(new CacheHealthChecker(countDownLatch));services.add(new DatabaseHealthChecker(countDownLatch));}private final static ApplicationStartupINSTANCEnew ApplicationStartup();privateApplicationStartup(){}public static ApplicationStartupgetInstance(){returnINSTANCE;}public static boolean checkExternalServices()throws InterruptedException{for(BaseHealthChecker bh:services){new Thread(bh).start();//针对每个服务采用线程来执行}countDownLatch.await();returntrue;}}StartupMain.javapackage cn.zxj.util;public class StartupMain{public static void main(String[]args){try{ApplicationStartup.checkExternalServices();}catch(InterruptedException e){//有问题了.}System.out.println(服务启动成功);}}1.3 CountDownLatch的实现原理计数器思想countDown调用一次state减一次直到state减为0就会同时唤醒所有被阻塞的线程允许多个线程同时抢占到锁(共享锁的实现)。二、Semaphore2.1 semaphore介绍作用限流器限制资源的访问。抢占一个令牌如果抢占到令牌就通行 否则就阻塞!方法acquire() 抢占一个令牌release() 释放一个令牌示例Semaphore semaphorenew Semaphore(10);acquire 10 - 1为0的时候阻塞有可能同时阻塞N个线程release 令牌1有令牌了唤醒。从阻塞的线程中去唤醒。为什么要用共享锁因为同时可以释放多个令牌那么意味着可以同时有多个线程抢占到锁。2.2 semaphore应用package cn.zxj.util;importjava.util.concurrent.Semaphore;importjava.util.concurrent.TimeUnit;public class SemaphoreExample{public static void main(String[]args){//限制资源的并发数量. Semaphoresemaphorenew Semaphore(10);for(int i0;i20;i){new Car(i,semaphore).start();}}static class Car extends Thread{private int num;private Semaphore semaphore;public Car(int num, Semaphore semaphore){this.numnum;this.semaphoresemaphore;}Override public voidrun(){try{semaphore.acquire();//获得一个令牌 System.out.println(第 num俩车抢到一个车位);TimeUnit.SECONDS.sleep(2);System.out.println(第 num走喽~);}catch(InterruptedException e){e.printStackTrace();}finally{semaphore.release();//释放一个令牌}}}}三、CyclicBarrier循环栅栏作用类似于CountDownLatch也可用来进行第三方的组件健康监测主要方法await() 进行减1并阻塞当前线程直到减为0唤醒所有阻塞的线程package cn.zxj.util;importjava.util.concurrent.BrokenBarrierException;importjava.util.concurrent.CyclicBarrier;public class CyclicBarrierExample{public static void main(String[]args){int n4;//parties 表示计数总数也就是参与的线程总数 CyclicBarrier barriernew CyclicBarrier(4,()-{System.out.println(所有线程都写入完成继续处理其他任务);});//4或4的倍数程序才会结束否则会陷入无限等待for(int i0;in;i){new Writer(barrier).start();}}static class Writer extends Thread{private CyclicBarrier cyclicBarrier;public Writer(CyclicBarrier barrier){this.cyclicBarrierbarrier;}Override public voidrun(){try{Thread.sleep(1000);System.out.println(Thread.currentThread().getName()写入数据完毕等待其他线程);cyclicBarrier.await();//-1的动作}catch(InterruptedException e){e.printStackTrace();}catch(BrokenBarrierException e){e.printStackTrace();}}}}