多執行緒(十二): 訊號量Semaphore
阿新 • • 發佈:2018-11-08
應用場景:多個執行緒使用數量有限的資源。
Semaphore是一種基於計數的訊號量。它可以設定一個閥值,基於此,多個執行緒競爭獲取許可訊號,做自己的申請後歸還,超過閥值後,執行緒申請許可訊號將會被阻塞。
Semaphore可以用來構建一些物件池,資源池之類的,比如資料庫連線池,我們也可以建立計數為1的Semaphore,將其作為一種類似互斥鎖的機制,這也叫二元訊號量,表示兩種互斥狀態。
public class Semaphore implements java.io.Serializable {
// 最多支援N個資源訪問
public Semaphore(int permits);
// 獲取可用的資源,
// 如果可用, 訊號量內部的資源個數減掉1,
// 如果沒有可用資源執行緒會阻塞在該方法中,不能結束該方法,不能返回,直到有可用的資源為止
public void acquire() throws InterruptedException;
// 當前可用的資源個數, permits - availablePermits() = 正在使用的資源個數
public int availablePermits();
// 釋放資源,釋放後訊號量內部的資源個數會增加1
// 如果有被阻塞的執行緒,釋放後會喚醒一個執行緒去獲取資源
// acquire() 和 release()要成對使用,一般release()放在finally程式碼塊中
public void release();
}
public class SemaphoreTest {
public static void main(String[] args) {
Semaphore semaphore = new Semaphore(3);
for (int i = 1; i <= 10; i++) {
new Thread(new MyRunnable(semaphore), "第" + i + "個人").start();
}
}
}
class MyRunnable implements Runnable {
private Semaphore semaphore;
public MyRunnable(Semaphore semaphore) {
this.semaphore = semaphore;
}
@Override
public void run() {
String name = Thread.currentThread().getName();
int availablePermits = semaphore.availablePermits();
if (availablePermits > 0) {
System.out.println(name + "無人,可用");
} else {
System.out.println(name + "有人,請排隊。。。\t?");
}
try {
// 如果沒有拿到資源將一直等待,直到有人釋放,拿到資源
semaphore.acquire();
System.out.println(name + "輪到我了");
// 模擬使用時間
Thread.sleep(1000);
System.out.println(name + "使用完畢\t?");
} catch (InterruptedException e) {
} finally {
// 使用完釋放資源
semaphore.release();
}
}
}