首页 > 代码库 > 线程:Semaphore实现信号灯

线程:Semaphore实现信号灯

  Semaphore是一个计数的信号量,可以维护当前访问自身的线程个数,并提供了同步机制。使用Semaphore可以控制同时访问资源的线程个数,例如实现一个文件允许的线程访问数。打个通俗的比喻,Semaphore实现的功能类似厕所有4个坑,假如有10个人上厕所,那么同时有多少个人去上厕所呢?同时只能有4个人能够占用,当4个人中的任何一个人让开后,其中在等待的另外6个人又有一个可以占用了。

 1 package ch03;
 2 
 3 import java.util.concurrent.ExecutorService;
 4 import java.util.concurrent.Executors;
 5 import java.util.concurrent.Semaphore;
 6 
 7 public class SemaphoreTest {
 8 
 9     public static void main(String[] args) {
10         ExecutorService threadPool = Executors.newCachedThreadPool();
11         //获取三个许可的信号灯
12         final Semaphore sp = new Semaphore(5);
13         for(int i=1; i<=10; i++){
14             final int index = i;
15             Runnable runable = new Runnable() {
16                 
17                 @Override
18                 public void run() {
19                     try {
20                         //获取一个信号灯
21                         sp.acquire();
22                     } catch (InterruptedException e) {
23                         e.printStackTrace();
24                     }
25                     System.out.println("有一个"+Thread.currentThread().getName()+
26                             "线程进来了,当前有"+(5-sp.availablePermits())+"线程正在并发...");
27                     
28                     try {
29                         Thread.sleep(index * 1000);
30                     } catch (InterruptedException e) {
31                         e.printStackTrace();
32                     }
33                     //释放信号灯
34                     sp.release();
35                     System.out.println("线程"+Thread.currentThread().getName()+"离开了,现在还有"+(5-sp.availablePermits())+"个线程!");
36                 }
37             };
38             threadPool.execute(runable);
39         }
40         threadPool.shutdown();
41     }
42 
43 }

至于,在等待的6个人中谁先进去,有两种方式:一种是看谁快,第二种是按排序,先来的先进去。可以通过Semaphore的构造函数指定:

如果使用排序的方式,可以将fair设为true.

 

除此之外,单个信号量的Semaphore对象还可以实现互斥锁的功能,只有一个灯,A线程获得,B线程就等着。传统的互斥锁,同一个线程的锁只能由自己释放,但Semaphore对象的互斥锁可以是由一个线程获得锁,再由另外一个线程释放锁,可以应用于死锁恢复的场合。比如一个人进厕所后,晕在里面了,这样的话可以去找管理员拿备用钥匙,打开门将人挪出来,这样就避免后面的人一直堵在这里。