在操作系統(tǒng)中,信號量是個很重要的概念,它在控制進程間的協(xié)作方面有著非常重要的作用,通過對信號量的不同操作,可以分別實現(xiàn)進程間的互斥與同步。當(dāng)然它也可以用于多線程的控制,我們完全可以通過使用信號量來自定義實現(xiàn)類似 Java 中的 synchronized、wait、notify 機制。
Java 并發(fā)包中的信號量 Semaphore 實際上是一個功能完畢的計數(shù)信號量,從概念上講,它維護了一個許可集合,對控制一定資源的消費與回收有著很重要的意義。Semaphore 可以控制某個資源被同時訪問的任務(wù)數(shù),它通過acquire()獲取一個許可,release()釋放一個許可。如果被同時訪問的任務(wù)數(shù)已滿,則其他 acquire 的任務(wù)進入等待狀態(tài),直到有一個任務(wù)被 release 掉,它才能得到許可。
下面給出一個采用 Semaphore 控制并發(fā)訪問數(shù)量的示例程序:
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Semaphore;
public class SemaphoreTest{
public static void main(String[] args) {
//采用新特性來啟動和管理線程——內(nèi)部使用線程池
ExecutorService exec = Executors.newCachedThreadPool();
//只允許5個線程同時訪問
final Semaphore semp = new Semaphore(5);
//模擬10個客戶端訪問
for (int index = 0; index < 10; index++){
final int num = index;
Runnable run = new Runnable() {
public void run() {
try {
//獲取許可
semp.acquire();
System.out.println("線程" +
Thread.currentThread().getName() + "獲得許可:" + num);
//模擬耗時的任務(wù)
for (int i = 0; i < 999999; i++) ;
//釋放許可
semp.release();
System.out.println("線程" +
Thread.currentThread().getName() + "釋放許可:" + num);
System.out.println("當(dāng)前允許進入的任務(wù)個數(shù):" +
semp.availablePermits());
}catch(InterruptedException e){
e.printStackTrace();
}
}
};
exec.execute(run);
}
//關(guān)閉線程池
exec.shutdown();
}
}
某次執(zhí)行的結(jié)果如下:
線程pool-1-thread-1獲得許可:0
線程pool-1-thread-1釋放許可:0
當(dāng)前允許進入的任務(wù)個數(shù):5
線程pool-1-thread-2獲得許可:1
線程pool-1-thread-6獲得許可:5
線程pool-1-thread-4獲得許可:3
線程pool-1-thread-8獲得許可:7
線程pool-1-thread-2釋放許可:1
當(dāng)前允許進入的任務(wù)個數(shù):2
線程pool-1-thread-5獲得許可:4
線程pool-1-thread-8釋放許可:7
線程pool-1-thread-3獲得許可:2
線程pool-1-thread-4釋放許可:3
線程pool-1-thread-10獲得許可:9
線程pool-1-thread-6釋放許可:5
線程pool-1-thread-10釋放許可:9
當(dāng)前允許進入的任務(wù)個數(shù):2
線程pool-1-thread-3釋放許可:2
當(dāng)前允許進入的任務(wù)個數(shù):1
線程pool-1-thread-5釋放許可:4
當(dāng)前允許進入的任務(wù)個數(shù):3
線程pool-1-thread-7獲得許可:6
線程pool-1-thread-9獲得許可:8
線程pool-1-thread-7釋放許可:6
當(dāng)前允許進入的任務(wù)個數(shù):5
當(dāng)前允許進入的任務(wù)個數(shù):3
當(dāng)前允許進入的任務(wù)個數(shù):3
當(dāng)前允許進入的任務(wù)個數(shù):3
線程pool-1-thread-9釋放許可:8
當(dāng)前允許進入的任務(wù)個數(shù):5
可以看出,Semaphore 允許并發(fā)訪問的任務(wù)數(shù)一直為 5,當(dāng)然,這里還很容易看出一點,就是 Semaphore 僅僅是對資源的并發(fā)訪問的任務(wù)數(shù)進行監(jiān)控,而不會保證線程安全,因此,在訪問的時候,要自己控制線程的安全訪問。