java并发之Semaphore

一、定义

  一个计数信号量。从概念上讲,信号量维护了一个许可集。如有必要,在许可可用前会阻塞每一个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     @Override
37     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这个信号量中当前可用的许可数:2
main正在等待获取的线程的估计数目:0
pool-1-thread-1begin...
pool-1-thread-2begin...
pool-1-thread-3begin...
pool-1-thread-4begin...
pool-1-thread-5begin...
mainsemaphore这个信号量中当前可用的许可数:0
main正在等待获取的线程的估计数目:3
mainsemaphore这个信号量中当前可用的许可数:0
main正在等待获取的线程的估计数目:3
mainsemaphore这个信号量中当前可用的许可数:0
main正在等待获取的线程的估计数目:3
mainsemaphore这个信号量中当前可用的许可数:0
main正在等待获取的线程的估计数目:3
pool-1-thread-1end...
pool-1-thread-2end...
mainsemaphore这个信号量中当前可用的许可数:0
main正在等待获取的线程的估计数目:1
mainsemaphore这个信号量中当前可用的许可数:0
main正在等待获取的线程的估计数目:1
mainsemaphore这个信号量中当前可用的许可数:0
main正在等待获取的线程的估计数目:1
mainsemaphore这个信号量中当前可用的许可数:0
main正在等待获取的线程的估计数目:1
mainsemaphore这个信号量中当前可用的许可数:0
main正在等待获取的线程的估计数目:1
pool-1-thread-3end...
pool-1-thread-4end...
mainsemaphore这个信号量中当前可用的许可数:1
main正在等待获取的线程的估计数目:0
mainsemaphore这个信号量中当前可用的许可数:1
main正在等待获取的线程的估计数目:0
mainsemaphore这个信号量中当前可用的许可数:1
main正在等待获取的线程的估计数目:0
mainsemaphore这个信号量中当前可用的许可数:1
main正在等待获取的线程的估计数目:0
mainsemaphore这个信号量中当前可用的许可数:1
main正在等待获取的线程的估计数目:0
pool-1-thread-5end...
mainsemaphore这个信号量中当前可用的许可数:2
main正在等待获取的线程的估计数目:0

 

posted @ 2017-04-14 19:54  夏威夷8080  阅读(455)  评论(0编辑  收藏  举报