semaphore(信号量)使用说明

例子:
     以一个停车场运作为例。为了简单起见,假设停车场只有三个车位,一开始三个车位都是空的。这时如果同时来了五辆车,看门人允许其中三辆不受阻碍的进入,然后放下车拦,剩下的车则必须在入口等待,此后来的车也都不得不在入口处等待。这时,有一辆车离开停车场,看门人得知后,打开车拦,放入一辆,如果又离开两辆,则又可以放入两辆,如此往复。
    在这个停车场系统中,车位是公共资源,每辆车好比一个线程,看门人起的就是信号量的作用。
     更进一步,信号量的特性如下:信号量是一个非负整数(车位数),所有通过它的线程(车辆)都会将该整数减一(通过它当然是为了使用资源),当该整数值为零时,所有试图通过它的线程都将处于等待状态。在信号量上我们定义两种操作: Wait(等待) 和 Release(释放)。 当一个线程调用Wait(等待)操作时,它要么通过然后将信号量减一,要么一直等下去,直到信号量大于一或超时。Release(释放)实际上是在信号量上执行加操作,对应于车辆离开停车场,该操作之所以叫做“释放”是因为加操作实际上是释放了由信号量守护的资源。
    
     Java并发库Semaphore 可以很轻松完成信号量控制,Semaphore可以控制某个资源可被同时访问的个数,通过 acquire() 获取一个许可,如果没有就等待,而 release() 释放一个许可。
 
代码示例:
     
 1 import java.util.concurrent.ExecutorService;
 2 import java.util.concurrent.Executors;
 3 import java.util.concurrent.Semaphore;
 4  
 5 public class SemaphoreTest {
 6         public static void main(String[] args) {
 7               ExecutorService service = Executors. newCachedThreadPool();
 8                final Semaphore sp = new Semaphore(3);
 9                for (int i = 0; i < 10; i++) {
10                      Runnable runnable = new Runnable() {
11                             public void run() {
12                                    try {
13                                          sp.acquire();
14                                   } catch (InterruptedException e1) {
15                                          e1.printStackTrace();
16                                   }
17                                   System. out.println("线程" + Thread.currentThread().getName() + "进入,当前已有" + (3 - sp.availablePermits()) + "个并发" );
18                                    try {
19                                          Thread. sleep((long) (Math. random() * 10000));
20                                   } catch (InterruptedException e) {
21                                          e.printStackTrace();
22                                   }
23                                   System. out.println("线程" + Thread.currentThread().getName() + "即将离开");
24                                   sp.release();
25  
26                                    // 下面代码有时候执行不准确,因为其没有和上面的代码合成原子单元
27                                    // availablePermits()指的是当前信号灯库中有多少个可以被使用
28                                   System. out.println("线程" + Thread.currentThread().getName() + "已离开,当前已有" + (3 - sp.availablePermits()) + "个并发" );
29                            }
30                      };
31                      service.execute(runnable);
32               }
33        }
34  
35 }

 

posted @ 2015-11-27 10:11  吞噬天帝  阅读(492)  评论(0编辑  收藏  举报