這篇文章介紹的 java.util.concurrent.Semaphore類是一個計數信号量。它有兩個主要的方法:
- acquire()
- release()
計數信号量在初始化的時候指定一定數量的許可N,意味着在允許N個線程通路自願。當線程調用 acquire() ,一個許可被占用,沒有許可的時候就等待;而 release() 意味着釋放一個許可,Semaphore是Java的一個簡單的計數器。
兩種用法
- 保護重要部分的代碼最多被N個線程通路。
- 單個信号量的Semaphore對象可以實作互斥鎖的功能,并且可以是由一個線程獲得了“鎖”,再由另一個線程釋放“鎖”,這可應用于死鎖恢複的一些場合。
代碼執行個體
public class SemaphoreTest {
private static final int THREAD_COUNT = ; // 線程數量設定30個
private static ExecutorService threadPool = Executors
.newFixedThreadPool(THREAD_COUNT);
private static Semaphore s = new Semaphore(); // 允許十個線程并發
public static void main(String[] args) {
for (int i = ; i < THREAD_COUNT; i++) {
threadPool.execute(new Runnable() {
@Override
public void run() {
try {
s.acquire();
System.out.println("save data");
s.release();
} catch (InterruptedException e) {
}
}
});
}
threadPool.shutdown();
}
}
在代碼中,雖然有30個線程在執行,但是隻允許10個并發的執行。Semaphore的構造方法Semaphore(int permits) 接受一個整型的數字,表示可用的許可證數量。Semaphore(10)表示允許10個線程擷取許可證,也就是最大并發數是10。Semaphore的用法也很簡單,首先線程使用Semaphore的acquire()擷取一個許可證,使用完之後調用release()歸還許可證。還可以用tryAcquire()方法嘗試擷取許可證。
其他方法
- int availablePermits() :傳回此信号量中目前可用的許可證數。
- int getQueueLength():傳回正在等待擷取許可證的線程數。
- boolean hasQueuedThreads() :是否有線程正在等待擷取許可證。
- void reducePermits(int reduction) :減少reduction個許可證。是個protected方法。
- Collection getQueuedThreads() :傳回所有等待擷取許可證的線程集合。是個protected方法。
公平性
Semaphore不保證第一個調用acquire() 方法的線程就是第一個獲得許可通路資源的線程。但是如果需要強制制造公平,Semaphore 提供了下面的構造方法,這種方法會有損Semaphore 的并發性,除非是必要使用公平性,否則不建議使用它。
Semaphore semaphore = new Semaphore(, true);