一个计数信号量。从概念上讲,信号量维护了一个许可集合。如有必要,在许可可用前会阻塞每一个 acquire(),然后再获取该许可。每个 release() 添加一个许可,从而可能释放一个正在阻塞的获取者。但是,不使用实际的许可对象,Semaphore 只对可用许可的号码进行计数,并采取相应的行动。
Semaphore 通常用于限制可以访问某些资源(物理或逻辑的)的线程数目。
获得一项前,每个线程必须从信号量获取许可,从而保证可以使用该项。该线程结束后,将项返回到池中并将许可返回到该信号量,从而允许其他线程获取该项。注意,调用 acquire() 时无法保持同步锁定,因为这会阻止将项返回到池中。信号量封装所需的同步,以限制对池的访问,这同维持该池本身一致性所需的同步是分开的。
将信号量初始化为 1,使得它在使用时最多只有一个可用的许可,从而可用作一个相互排斥的锁。这通常也称为二进制信号量,因为它只能有两种状态:一个可用的许可,或零个可用的许可。按此方式使用时,二进制信号量具有某种属性(与很多 Lock 实现不同),即可以由线程释放“锁定”,而不是由所有者(因为信号量没有所有权的概念)。在某些专门的上下文(如死锁恢复)中这会很有用。
构造方法:
a. Semaphore(int permits):用给定的许可数和非公平的公平设置创建一个 Semaphore。
b. Semaphore(int permits, boolean fair):用给定的许可数和给定的公平设置创建一个 Semaphore。
实例:
java">package com.bijian.thread;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Semaphore;
public class Main {
/**
* @param args
*/
public static void main(String[] args) {
// 线程池
ExecutorService exec = Executors.newCachedThreadPool();
// 只能5个线程同时访问
final Semaphore semp = new Semaphore(5);
// 模拟20个客户端访问
for (int index = 0; index < 20; index++) {
final int NO = index;
Runnable run = new Runnable() {
public void run() {
try {
// 获取许可
semp.acquire();
System.out.println(Thread.currentThread().getName() + ": Accessing: " + NO);
Thread.sleep((long) (Math.random() * 1000));
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
// 访问完后,释放
semp.release();
System.out.println("-----------------" + semp.availablePermits());
}
}
};
exec.execute(run);
}
// 退出线程池
exec.shutdown();
}
}
运行结果:
pool-1-thread-1: Accessing: 0 pool-1-thread-4: Accessing: 3 pool-1-thread-3: Accessing: 2 pool-1-thread-2: Accessing: 1 pool-1-thread-6: Accessing: 5 -----------------1 pool-1-thread-8: Accessing: 7 -----------------1 pool-1-thread-7: Accessing: 6 -----------------1 pool-1-thread-9: Accessing: 8 -----------------1 pool-1-thread-10: Accessing: 9 -----------------1 pool-1-thread-5: Accessing: 4 -----------------1 pool-1-thread-11: Accessing: 10 -----------------1 pool-1-thread-12: Accessing: 11 -----------------1 pool-1-thread-13: Accessing: 12 -----------------1 pool-1-thread-14: Accessing: 13 -----------------1 pool-1-thread-15: Accessing: 14 -----------------1 pool-1-thread-16: Accessing: 15 -----------------1 pool-1-thread-17: Accessing: 16 -----------------1 pool-1-thread-18: Accessing: 17 -----------------1 pool-1-thread-19: Accessing: 18 -----------------1 pool-1-thread-20: Accessing: 19 -----------------1 -----------------2 -----------------3 -----------------4 -----------------5