一、Semaphore的概念
Semaphore(信號量)是一種用於保護共享資源的並發訪問的同步工具,它可以用來控制同時訪問某個資源的線程個數。Semaphore是一種計數器,每當一個線程訪問該資源時,計數器減1,當計數器為0時,其他試圖訪問該資源的線程會被阻塞,直到計數器變為大於0才能再繼續訪問。
在Java中,Semaphore是一個類,定義如下:
public class Semaphore { public Semaphore(int permits); public Semaphore(int permits, boolean fair); public void acquire() throws InterruptedException; public void release(); public int availablePermits(); }
Semaphore的構造函數可接受一個整型參數,該參數是此同步器能夠支持的線程數,並通過acquire()和release()方法來獲取和釋放Semophore對象,availablePermits()方法可獲取可用的許可數。
二、Semaphore的應用場景
Semaphore適用於需要控制線程數目的場景,例如:
- 數據庫連接池
- 線程池
- 讀寫鎖
- 文件流量控制等
三、Semaphore的使用示例
下面以一個簡單的例子來說明Semaphore的使用方法。
需求:模擬20個線程同時寫入文件,並提供3個文件輸出流,以控制同時寫入文件的線程數不超過3個。
import java.io.FileWriter; import java.io.IOException; import java.util.concurrent.Semaphore; public class SemaphoreDemo { public static void main(String[] args) { Semaphore semaphore = new Semaphore(3); for (int i = 1; i <= 20; i++) { Thread thread = new Thread(new Runnable() { @Override public void run() { try { semaphore.acquire(); FileWriter writer = new FileWriter("output.txt", true); writer.write(Thread.currentThread().getName() + "\n"); writer.close(); semaphore.release(); } catch (IOException | InterruptedException e) { e.printStackTrace(); } } }, "Thread " + i); thread.start(); } } }
第一步,創建Semaphore對象,設置許可個數為3。
第二步,循環20次,每次創建一個線程來讀寫文件,使用Semaphore對象控制訪問許可數。
第三步,線程運行時會從Semaphore對象獲取一個許可,執行文件讀寫操作,完成後釋放許可。
通過這種方式,實現了同時寫入文件的線程數不超過3個,達到了控制並發訪問的目的。
四、Semaphore的注意事項
在使用Semaphore時需要注意以下幾點:
- Semaphore的許可數不是可重入鎖,也就是說如果一個線程已經獲得了一個許可,再次調用acquire()方法時會被阻塞。
- 如果沒有許可可用,acquire()方法會一直阻塞,直到有許可可用。
- release()方法是釋放許可,如果釋放的許可數超過了原來的許可數,會拋出IllegalArgumentException異常。
五、總結
Semaphore是一種非常有用的並發控制工具,可以靈活地控制線程的並發訪問,具有廣泛的應用場景。在使用Semaphore時需要注意其許可數和許可的獲取和釋放,以免出現死鎖等問題。
原創文章,作者:KRLRB,如若轉載,請註明出處:https://www.506064.com/zh-hk/n/368251.html