一. Semaphore實現信號燈
Semaphore可以控制同時訪問資源的線程個數, 例如: 實現一個文件允許的並發訪問數.
Semaphore實現的功能就類似廁所有5個坑, 加入有十個人要上廁所, 那麼同時只能有5個人能夠占用, 當5個人中的任何一個人離開後, 其中在等待的另外5個人中就有一個可以占用了. 另外等待的5個人中可以是隨機獲得優先機會, 也可以使按照先來後到的順序獲得機會, 這取決於構造Semaphore對象時傳入的參數選項.
/**
* Semaphore:信號燈
*/
public class SemaphoreTest {
public static void main(String[] args) {
// 創建一個線程池
ExecutorService es = Executors.newCachedThreadPool();
// 允許並發訪問的線程個數為3個
final Semaphore sp = new Semaphore(3);
// 開啟10個線程
for (int i = 0; i < 10; i++) {
es.execute(new Runnable() {
@Override
public void run() {
try {
sp.acquire(); // 獲取信號燈
System.out.println("線程 " + Thread.currentThread().getName()
+ " 進入,當前有 " + (3 - sp.availablePermits()) + " 個並發!");
Thread.sleep(2000);
System.out.println("線程 " + Thread.currentThread().getName() + " 即將離開!");
sp.release(); // 釋放信號燈
System.out.println("線程 " + Thread.currentThread().getName()
+ " 離開,當前有 " + (3 - sp.availablePermits()) + " 個並發!");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
}
}
}
單個Semaphore對象可以實現互斥鎖的功能, 並且可以是由一個線程獲得了"鎖", 再由另一個線程釋放"鎖", 這可應用於死鎖恢復的一些場合.
public class CyclicBarrierTest {
public static void main(String[] args) {
ExecutorService service = Executors.newCachedThreadPool();
final CyclicBarrier cb = new CyclicBarrier(3);
// 創建3個線程
for(int i=0;i<3;i++){
service.execute(new Runnable(){
@Override
public void run(){
try {
Thread.sleep((long)(Math.random() * 10000));//每個線程“休息的”時間不同
System.out.println("線程" + Thread.currentThread().getName()
+ "即將到達集合地點1,當前已有" + (cb.getNumberWaiting() + 1)
+ "個已經到達," + (cb.getNumberWaiting() == 2 ? "都到齊了,繼續前進":"正在等候"));
cb.await(); //先到的等待後到的,當3個都到達時才會繼續向下執行
Thread.sleep((long)(Math.random() * 10000));//每個線程“休息的”時間不同
System.out.println("線程" + Thread.currentThread().getName()
+ "即將到達集合地點2,當前已有" + (cb.getNumberWaiting() + 1)
+ "個已經到達," + (cb.getNumberWaiting() == 2 ? "都到齊了,繼續前進":"正在等候"));
cb.await();
Thread.sleep((long)(Math.random()*10000));//每個線程“休息的”時間不同
System.out.println("線程" + Thread.currentThread().getName()
+ "即將到達集合地點3,當前已有" + (cb.getNumberWaiting() + 1)
+ "個已經到達,"+ (cb.getNumberWaiting() == 2 ? "都到齊了,繼續前進":"正在等候"));
cb.await();
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
service.shutdown();
}
}