一、定义
一个计数信号量。从概念上讲,信号量维护了一个许可集。如有必要,在许可可用前会阻塞每一个acquire()
,然后再获取该许可。每个release()
添加一个许可,从而可能释放一个正在阻塞的获取者。但是,不使用实际的许可对象,Semaphore
只对可用许可的号码进行计数,并采取相应的行动。
Semaphore通常用于限制可以访问某些资源(物理或逻辑的)的线程数目。
二、使用场景代码示例
比方说我们有个资源访问连接池,每次只能同时允许2个线程访问资源,当某个线程或许到资格访问资源业务完成线程结束,它还要自动释放,让其它线程可以访问。
1 public class Test { 2 3 public static void main(String[] args) throws IOException { 4 ExecutorService executorService = Executors.newCachedThreadPool(); 5 // 配置同时只能有两个线程访问 6 Semaphore semaphore = new Semaphore(2); 7 // 开启10个线程 8 for (int i = 0; i < 10; i++) { 9 executorService.execute(new TaskRunn(semaphore));10 }11 // 关闭线程池12 executorService.shutdown();13 while (true) {14 System.out.println(Thread.currentThread().getName()+"semaphore这个信号量中当前可用的许可数:"+semaphore.availablePermits());15 System.out.println(Thread.currentThread().getName()+"正在等待获取的线程的估计数目:"+semaphore.getQueueLength());16 // System.out.println(Thread.currentThread().getName()+"查询是否有线程正在等待获取:"+semaphore.hasQueuedThreads());17 if (semaphore.getQueueLength() == 0) {18 break;19 }20 try {21 Thread.sleep(1000);22 } catch (InterruptedException e) {23 e.printStackTrace();24 }25 }26 }27 }28 29 class TaskRunn implements Runnable{30 31 private Semaphore semaphore;32 public TaskRunn(Semaphore semaphore) {33 this.semaphore = semaphore;34 }35 36 @Override37 public void run() {38 try {39 System.out.println(Thread.currentThread().getName()+"begin...");40 semaphore.acquire();// 从此信号量获取一个许可,在提供一个许可前一直将线程阻塞,否则线程被中断41 Thread.sleep(5000);// 模拟业务耗时42 semaphore.release();// 释放一个许可,将其返回给信号量43 System.out.println(Thread.currentThread().getName()+"end...");44 } catch (InterruptedException e) {45 e.printStackTrace();46 }47 }48 49 }
打印信息
mainsemaphore这个信号量中当前可用的许可数:2main正在等待获取的线程的估计数目:0pool-1-thread-1begin...pool-1-thread-2begin...pool-1-thread-3begin...pool-1-thread-4begin...pool-1-thread-5begin...mainsemaphore这个信号量中当前可用的许可数:0main正在等待获取的线程的估计数目:3mainsemaphore这个信号量中当前可用的许可数:0main正在等待获取的线程的估计数目:3mainsemaphore这个信号量中当前可用的许可数:0main正在等待获取的线程的估计数目:3mainsemaphore这个信号量中当前可用的许可数:0main正在等待获取的线程的估计数目:3pool-1-thread-1end...pool-1-thread-2end...mainsemaphore这个信号量中当前可用的许可数:0main正在等待获取的线程的估计数目:1mainsemaphore这个信号量中当前可用的许可数:0main正在等待获取的线程的估计数目:1mainsemaphore这个信号量中当前可用的许可数:0main正在等待获取的线程的估计数目:1mainsemaphore这个信号量中当前可用的许可数:0main正在等待获取的线程的估计数目:1mainsemaphore这个信号量中当前可用的许可数:0main正在等待获取的线程的估计数目:1pool-1-thread-3end...pool-1-thread-4end...mainsemaphore这个信号量中当前可用的许可数:1main正在等待获取的线程的估计数目:0mainsemaphore这个信号量中当前可用的许可数:1main正在等待获取的线程的估计数目:0mainsemaphore这个信号量中当前可用的许可数:1main正在等待获取的线程的估计数目:0mainsemaphore这个信号量中当前可用的许可数:1main正在等待获取的线程的估计数目:0mainsemaphore这个信号量中当前可用的许可数:1main正在等待获取的线程的估计数目:0pool-1-thread-5end...mainsemaphore这个信号量中当前可用的许可数:2main正在等待获取的线程的估计数目:0