一. 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(); } }