java.util.concurrent
Class Semaphore
Semaphore常用来限制一定数量的线程来访问某个共享资源。一个Semaphore控制了一组令牌。除非存在可使用的令牌否则在调用acquire去获得资源时
将会被阻塞。release方法就是释放令牌,潜在的能够为acquire提供令牌,使得令牌的重复利用。然而,并没有真实的令牌对象,Semaphore仅仅只是拥有
一个数字。
在获得资源前,每个线程必须从Semaphore获得一个令牌。
一个Semaphore被初始化为1,也就是Semaphore只有一个令牌可用,于是可以作为互斥锁来使用。这就是我们众所周知的二进制Semaphore,因为它只有两种
状态:如果为1,则有一个令牌可使用,如果为0,则没有令牌可使用。
它的构造函数可以接受一个boolean型的可选参数。如果我们设置为false,就不能保证线程以什么样的顺序获得令牌。如果设置为true,就会以先进先出的顺序获得
令牌。
1 class Pool { 2 private static final int MAX_AVAILABLE = 100; 3 private final Semaphore available = new Semaphore(MAX_AVAILABLE, true); 4 5 public Object getItem() throws InterruptedException { 6 available.acquire(); 7 return getNextAvailableItem(); 8 } 9 10 public void putItem(Object x) { 11 if (markAsUnused(x)) 12 available.release(); 13 } 14 15 // 没有一个特殊有效的数据结构这个仅仅只是作为例子 16 17 protected Object[] items =new Object[10000]; //任何所管理的项 18 protected boolean[] used = new boolean[MAX_AVAILABLE]; 19 20 protected synchronized Object getNextAvailableItem() { 21 for (int i = 0; i < MAX_AVAILABLE; ++i) { 22 if (!used[i]) { 23 used[i] = true; 24 return items[i]; 25 } 26 } 27 return null; // 不能到达 28 } 29 30 protected synchronized boolean markAsUnused(Object item) { 31 for (int i = 0; i < MAX_AVAILABLE; ++i) { 32 if (item == items[i]) { 33 if (used[i]) { 34 used[i] = false; 35 return true; 36 } else 37 return false; 38 } 39 } 40 return false; 41 } 42 43 }
程序分析:
1、这里设置了有100个令牌的Semaphore。刚开始的时候,没有想明白,既然要给容器加上同步方法,还有必要加上Semaphore么?不管你放多少个线程进来,同时只能有一个线程能进行操作。
换一种想法,100个方法同步,与10000个方法同步,哪个对容器的影响大一些?就好像今天早上,我去坐北京天通苑的地铁,正常通向地铁的正门是被锁着的,而人群在两道铁门之间经过地铁站
中部然后迂回至正门。Semaphore就充当着两到铁门所围起来的空间的作用(如果空间被他人占用了,就没法前进),充当了一个缓冲作用。
2、Semaphore充当的缓冲作用,Semaphore并不提供同步,这也是为什么一定要给容器加上同步方法的原因。
原文:http://www.cnblogs.com/feijishuo/p/4538814.html