Semaphore 字面意思是信号量的意思,它的作用是控制访问特定资源的线程数目,底层依赖AQS的状态State,是在生产当中比较常用的一个工具类。
1 public Semaphore(int permits)
2 public Semaphore(int permits, boolean fair)
* permits表示许可线程的数量
* fair表示公平性,如果这个设为true的话,下次执行的线程会是等待最久的线程
1 public void acquire() throws InterruptedException 2 public void release() 3 tryAcquire(int args,long timeout, TimeUnit unit)
* acquire()表示阻塞并获取许可
* release()表示释放许可
资源访问,服务限流(Hystrix里限流就有基于信号量方式)。
1 public class SemaphoreRunner { 2 public static void main(String[] args) { 3 Semaphore semaphore = new Semaphore(2); 4 for (int i=0;i<5;i++){ 5 new Thread(new Task(semaphore,"yangguo+"+i)).start(); 6 } 7 } 8 9 static class Task extends Thread{ 10 Semaphore semaphore; 11 12 public Task(Semaphore semaphore,String tname){ 13 this.semaphore = semaphore; 14 this.setName(tname); 15 } 16 17 public void run() { 18 try { 19 semaphore.acquire(); 20 System.out.println(Thread.currentThread().getName()+":aquire() at time:"+System.currentTimeMillis()); 21 Thread.sleep(1000); 22 semaphore.release(); 23 System.out.println(Thread.currentThread().getName()+":aquire() at time:"+System.currentTimeMillis()); 24 } catch (InterruptedException e) { 25 e.printStackTrace(); 26 } 27 28 } 29 } 30 }
打印结果
CountDownLatch这个类能够使一个线程等待其他线程完成各自的工作后再执行。例如,应用程序的主线程希望在负责启动框架服务的线程已经启动所有的框架服务之后再执行。
使用场景:Zookeeper分布式锁,Jmeter模拟高并发等
CountDownLatch是通过一个计数器来实现的,计数器的初始值为线程的数量。每当一个线程完成了自己的任务后,计数器的值就会减1。当计数器值到达0时,它表示所有的线程已经完成了任务,然后在闭锁上等待的线程就可以恢复执行任务。
CountDownLatch.countDown()
CountDownLatch.await();
比如陪媳妇去看病。
1 /** 2 * 看大夫任务 3 */ 4 public class SeeDoctorTask implements Runnable { 5 private CountDownLatch countDownLatch; 6 7 public SeeDoctorTask(CountDownLatch countDownLatch){ 8 this.countDownLatch = countDownLatch; 9 } 10 11 public void run() { 12 try { 13 System.out.println("开始看医生"); 14 Thread.sleep(3000); 15 System.out.println("看医生结束,准备离开病房"); 16 } catch (InterruptedException e) { 17 e.printStackTrace(); 18 }finally { 19 if (countDownLatch != null) 20 countDownLatch.countDown(); 21 } 22 } 23 24 } 25 26 /** 27 * 排队的任务 28 */ 29 public class QueueTask implements Runnable { 30 31 private CountDownLatch countDownLatch; 32 33 public QueueTask(CountDownLatch countDownLatch){ 34 this.countDownLatch = countDownLatch; 35 } 36 public void run() { 37 try { 38 System.out.println("开始在医院药房排队买药...."); 39 Thread.sleep(5000); 40 System.out.println("排队成功,可以开始缴费买药"); 41 } catch (InterruptedException e) { 42 e.printStackTrace(); 43 }finally { 44 if (countDownLatch != null) 45 countDownLatch.countDown(); 46 } 47 } 48 } 49 50 /** 51 * 配媳妇去看病,轮到媳妇看大夫时 52 * 我就开始去排队准备交钱了。 53 */ 54 public class CountDownLaunchRunner { 55 56 public static void main(String[] args) throws InterruptedException { 57 long now = System.currentTimeMillis(); 58 CountDownLatch countDownLatch = new CountDownLatch(2); 59 60 new Thread(new SeeDoctorTask(countDownLatch)).start(); 61 new Thread(new QueueTask(countDownLatch)).start(); 62 //等待线程池中的2个任务执行完毕,否则一直 63 countDownLatch.await(); 64 System.out.println("over,回家 cost:"+(System.currentTimeMillis()-now)); 65 } 66 }
cyclicBarrier.await();
应用场景
1 public class CyclicBarrierRunner implements Runnable { 2 private CyclicBarrier cyclicBarrier; 3 private int index ; 4 5 public CyclicBarrierTest(CyclicBarrier cyclicBarrier, int index) { 6 this.cyclicBarrier = cyclicBarrier; 7 this.index = index; 8 } 9 10 public void run() { 11 try { 12 System.out.println("index: " + index); 13 index--; 14 cyclicBarrier.await(); 15 } catch (Exception e) { 16 e.printStackTrace(); 17 } 18 } 19 20 public static void main(String[] args) throws Exception { 21 CyclicBarrier cyclicBarrier = new CyclicBarrier(11, new Runnable() { 22 public void run() { 23 System.out.println("所有特工到达屏障,准备开始执行秘密任务"); 24 } 25 }); 26 for (int i = 0; i < 10; i++) { 27 new Thread(new CyclicBarrierTest(cyclicBarrier, i)).start(); 28 } 29 cyclicBarrier.await(); 30 System.out.println("全部到达屏障...."); 31 } 32 }
主要用来创建线程池,代理了线程池的创建,使得你的创建入口参数变得简单
重要方法:
* newCachedThreadPool创建一个可缓存线程池,如果线程池长度超过处理需要,可灵活回收空闲线程,若无可回收,则新建线程。
* newFixedThreadPool 创建一个定长线程池,可控制线程最大并发数,超出的线程会在队列中等待。
* newScheduledThreadPool 创建一个定长线程池,支持定时及周期性任务执行。
* newSingleThreadExecutor 创建一个单线程化的线程池,它只会用唯一的工作线程来执行任务,保证所有任务按照指定顺序(FIFO, LIFO, 优先级)执行。
1 public class ExchangerTest { 2 3 public static void main(String []args) { 4 final Exchanger<Integer> exchanger = new Exchanger<Integer>(); 5 for(int i = 0 ; i < 10 ; i++) { 6 final Integer num = i; 7 new Thread() { 8 public void run() { 9 System.out.println("我是线程:Thread_" + this.getName() + "我的数据是:" + num); 10 try { 11 Integer exchangeNum = exchanger.exchange(num); 12 Thread.sleep(1000); 13 System.out.println("我是线程:Thread_" + this.getName() + "我原先的数据为:" + num + " , 交换后的数据为:" + exchangeNum); 14 } catch (InterruptedException e) { 15 e.printStackTrace(); 16 } 17 } 18 }.start(); 19 } 20 } 21 }
并发编程专题七:CountDownLatch&Semaphore应用与原理
原文:https://www.cnblogs.com/Mapi/p/14406449.html