Semaphore用来控制同时访问资源的线程数量,它通过协调各个线程,以保证合理使用公共资源。特别是公用资源有限的情况下,比如数据库连接。假如有一个需求,要读取几万个文件的数据,因为都是IO密集型任务,我们可以启动几十个线程并发读取,但是读到内存之后,还要存储到数据库,而数据库的连接只有5个,这时候,我们必须控制线程数量为5同时获取数据库连接,否则会报无法获取数据库连接。这个时候Semaphore就有用武之地了。
举个例子:
public class SemaphoreClient {
private static final int THREAD_COUNT = 20;
private static ExecutorService threadPool = Executors.newFixedThreadPool(THREAD_COUNT);
private static Semaphore semaphore = new Semaphore(2);
public static void main(String[] args) {
for (int i = 0; i < THREAD_COUNT; i++) {
final int x = i + 1;
threadPool.execute(new Runnable() {
@Override
public void run() {
try {
semaphore.acquire();
System.out.println("Save Data"+x);
System.out.println("AvailablePermits: "+semaphore.availablePermits());
System.out.println("QueueLength: "+semaphore.getQueueLength());
System.out.println("existsthread waiting: "+semaphore.hasQueuedThreads());
semaphore.release();
} catch(InterruptedException e) {
// TODO Auto-generatedcatch block
e.printStackTrace();
}
}
});
}
threadPool.shutdown();
}
}
上述代码有20个线程,但是只允许2个线程。其构造方法Semaphore(int Permits) 需要传递一个允许并发的线程数量。线程需要
使用Semaphore.acquire()去获取一个许可证,使用完之后归还许可证,还可以tryAcquire()方法尝试获取许可证。
availablePermits: 所允许的许可证
getQueueLength: 正在等待获取许可证的线程数
hasQueuedThreads: 是否有线程正在等待获取许可证。