Semaphore类
一个计数信号量。从概念上讲,信号量维护了一个许可集合。如有必要,在许可可用前会阻塞每一个 acquire(),然后再获取该许可。每个 release() 添加一个许可,从而可能释放一个正在阻塞的获取者。但是,不使用实际的许可对象,Semaphore 只对可用许可的号码进行计数,并采取相应的行动。
Semaphore 通常用于限制可以访问某些资源(物理或逻辑的)的线程数目。
获得一项前,每个线程必须从信号量获取许可,从而保证可以使用该项。该线程结束后,将项返回到池中并将许可返回到该信号量,从而允许其他线程获取该项。注意,调用 acquire() 时无法保持同步锁定,因为这会阻止将项返回到池中。信号量封装所需的同步,以限制对池的访问,这同维持该池本身一致性所需的同步是分开的。
将信号量初始化为 1,使得它在使用时最多只有一个可用的许可,从而可用作一个相互排斥的锁。这通常也称为二进制信号量,因为它只能有两种状态:一个可用的许可,或零个可用的许可。按此方式使用时,二进制信号量具有某种属性(与很多 Lock 实现不同),即可以由线程释放“锁定”,而不是由所有者(因为信号量没有所有权的概念)。在某些专门的上下文(如死锁恢复)中这会很有用。
构造方法:
a. Semaphore(int permits):用给定的许可数和非公平的公平设置创建一个 Semaphore。
b. Semaphore(int permits, boolean fair):用给定的许可数和给定的公平设置创建一个 Semaphore。
实例:
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