Semaphore 維護一組虛擬許可證(計數器),acquire() 獲取許可(不足則阻塞),release() 釋放許可(喚醒等待執行緒)。常用於限流、資源池隔離、併發訪問控制。
Semaphore(int permits, boolean fair)
permits:初始許可證數量(最大併發數)。fair:true 使用公平鎖(FIFO),false 非公平(預設,吞吐較高)。package com.thread.test.thread;
import java.util.Random;
import java.util.concurrent.*;
public class MySemaphore {
public static void main(String[] args) {
// 5 個許可,公平模式
Semaphore sp = new Semaphore(5, true);
ExecutorService es = Executors.newCachedThreadPool();
Random r = new Random();
for (int i = 0; i < 10; i++) {
// 隨機執行 0-9 秒,模擬不同業務耗時
es.execute(new Needer(sp, r.nextInt(10), "needer-" + i));
}
es.shutdown();
}
}
class Needer implements Runnable {
private final Semaphore sp;
private final int seconds;
private final String neederName;
Needer(Semaphore sp, int seconds, String neederName) {
this.sp = sp;
this.seconds = seconds;
this.neederName = neederName;
}
@Override
public void run() {
try {
sp.acquire(); // 獲取許可,阻塞直到可用
System.out.println("Needer " + neederName + " begin, need time: " + seconds + "s");
long start = System.currentTimeMillis();
for (int i = 0; i < seconds; i++) {
Thread.sleep(1000);
System.out.println("Needer: " + neederName + " ============ " + i + " ============");
}
long duration = System.currentTimeMillis() - start;
System.out.println("Needer " + neederName + " over, executing time: "
+ TimeUnit.SECONDS.convert(duration, TimeUnit.MILLISECONDS) + "s");
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
sp.release(); // 釋放許可,喚醒下一個等待者
}
}
}
Needer 能進入關鍵區執行。acquire() 處阻塞,按公平順序依次獲得許可。finally 確保釋放許可,防止死鎖。