public CountDownLatch(int count) { }; //參數count爲計數值
public void await() throws InterruptedException { }; //調用await()方法的線程會被掛起,它會等待直到count值爲0才繼續執行 public boolean await(long timeout, TimeUnit unit) throws InterruptedException { }; //和await()相似,只不過等待必定的時間後count值還沒變爲0的話就會繼續執行 public void countDown() { }; //將count值減1
package sychronized; import static net.mindview.util.Print.*; import java.util.concurrent.*; class Task implements Runnable{ private static int count = 0; private final int id = count++; final CountDownLatch latch ; public Task(CountDownLatch latch){ this.latch = latch; } @Override public void run(){ try { print(this+"正在執行"); TimeUnit.MILLISECONDS.sleep(3000); print(this+"執行完畢"); latch.countDown(); } catch (InterruptedException e) { print(this + " 被中斷"); } } @Override public String toString() { return "Task-"+id; } } public class Test { public static void main(String[] args) { final CountDownLatch latch = new CountDownLatch(2); ExecutorService exec = Executors.newCachedThreadPool(); exec.execute(new Task(latch)); exec.execute(new Task(latch)); try { print("等待2個子線程執行完畢..."); long start = System.currentTimeMillis(); latch.await(); long end = System.currentTimeMillis(); print("2個子線程已經執行完畢 "+(end - start)); print("繼續執行主線程"); }catch (InterruptedException e){ print("主線程被中斷"); } exec.shutdown(); } } #輸出結果: 等待2個子線程執行完畢... Task-0正在執行 Task-1正在執行 Task-0執行完畢 Task-1執行完畢 2個子線程已經執行完畢 3049 繼續執行主線程
public CyclicBarrier(int parties, Runnable barrierAction) {} public CyclicBarrier(int parties) {}
public int await() throws InterruptedException, BrokenBarrierException { }; public int await(long timeout, TimeUnit unit)throws InterruptedException,BrokenBarrierException,TimeoutException { };
package sychronized; import java.util.Random; import java.util.concurrent.*; import static net.mindview.util.Print.*; class WriteTask implements Runnable{ private static int count = 0; private final int id = count++; private CyclicBarrier barrier ; private static Random random = new Random(47); public WriteTask(CyclicBarrier cyclicBarrier) { this.barrier = cyclicBarrier; } @Override public void run() { print(this+"開始寫入數據..."); try { TimeUnit.MILLISECONDS.sleep(random.nextInt(5000)); //以睡眠來模擬寫入數據操做 print(this+"寫入數據完畢,等待其餘線程寫入完畢"+" "+System.currentTimeMillis()); barrier.await(); } catch (InterruptedException e) { print(this + "is interrupted!"); }catch(BrokenBarrierException e){ throw new RuntimeException(e); } print("全部任務寫入完畢,繼續處理其餘任務... "+System.currentTimeMillis()); } @Override public String toString() { return getClass().getSimpleName()+"-"+id; } } public class CyclicBarrierTest { public static void main(String[] args) { int N = 4; CyclicBarrier barrier = new CyclicBarrier(N); ExecutorService exec = Executors.newCachedThreadPool(); for(int i = 0; i < N; ++i){ exec.execute(new WriteTask(barrier)); } exec.shutdown(); } } #輸出結果: WriteTask-3 開始寫入數據... WriteTask-2 開始寫入數據... WriteTask-1 開始寫入數據... WriteTask-0 開始寫入數據... WriteTask-2 寫入數據完畢,等待其餘線程寫入完畢 1512048648904 WriteTask-1 寫入數據完畢,等待其餘線程寫入完畢 1512048650042 WriteTask-0 寫入數據完畢,等待其餘線程寫入完畢 1512048650209 WriteTask-3 寫入數據完畢,等待其餘線程寫入完畢 1512048652606 全部任務寫入完畢,繼續處理其餘任務... 1512048652607 全部任務寫入完畢,繼續處理其餘任務... 1512048652607 全部任務寫入完畢,繼續處理其餘任務... 1512048652607 全部任務寫入完畢,繼續處理其餘任務... 1512048652607
**java
**dom
package sychronized; import java.util.Random; import java.util.concurrent.*; import static net.mindview.util.Print.*; class WriteTask implements Runnable{ private static int count = 0; private final int id = count++; private CyclicBarrier barrier ; private static Random random = new Random(47); public WriteTask(CyclicBarrier cyclicBarrier) { this.barrier = cyclicBarrier; } @Override public void run() { print(this+" 開始寫入數據..."); try { TimeUnit.MILLISECONDS.sleep(random.nextInt(5000)); //以睡眠來模擬寫入數據操做 print(this+" 寫入數據完畢,等待其餘線程寫入完畢"+" "+System.currentTimeMillis()); barrier.await(); TimeUnit.MILLISECONDS.sleep(10); } catch (InterruptedException e) { print(this + "is interrupted!"); }catch(BrokenBarrierException e){ throw new RuntimeException(e); } print("全部任務寫入完畢,繼續處理其餘任務... "+System.currentTimeMillis()+Thread.currentThread()); } @Override public String toString() { return getClass().getSimpleName()+"-"+id; } } public class CyclicBarrierTest { public static void main(String[] args) { int N = 4; CyclicBarrier barrier = new CyclicBarrier(N, new Runnable() { @Override public void run() { print(Thread.currentThread()); } }); ExecutorService exec = Executors.newCachedThreadPool(); for(int i = 0; i < N; ++i){ exec.execute(new WriteTask(barrier)); } exec.shutdown(); } } #輸出結果爲: WriteTask-3 開始寫入數據... WriteTask-1 開始寫入數據... WriteTask-2 開始寫入數據... WriteTask-0 開始寫入數據... WriteTask-1 寫入數據完畢,等待其餘線程寫入完畢 1512049061954 WriteTask-2 寫入數據完畢,等待其餘線程寫入完畢 1512049063092 WriteTask-0 寫入數據完畢,等待其餘線程寫入完畢 1512049063261 WriteTask-3 寫入數據完畢,等待其餘線程寫入完畢 1512049065657 Thread[pool-1-thread-4,5,main] 全部任務寫入完畢,繼續處理其餘任務... 1512049065668Thread[pool-1-thread-2,5,main] 全部任務寫入完畢,繼續處理其餘任務... 1512049065668Thread[pool-1-thread-1,5,main] 全部任務寫入完畢,繼續處理其餘任務... 1512049065668Thread[pool-1-thread-4,5,main] 全部任務寫入完畢,繼續處理其餘任務... 1512049065668Thread[pool-1-thread-3,5,main]
從結果能夠看出,當四個線程都到達barrier狀態後,會從四個線程中選擇一個線程去執行Runnable。ide
package sychronized; import java.util.Random; import java.util.concurrent.*; import static net.mindview.util.Print.*; class WriteTask implements Runnable{ private static int count = 0; private final int id = count++; private CyclicBarrier barrier ; private static Random random = new Random(47); public WriteTask(CyclicBarrier cyclicBarrier) { this.barrier = cyclicBarrier; } @Override public void run() { while (!Thread.interrupted()){ print(this+" 開始寫入數據..."); try { TimeUnit.MILLISECONDS.sleep(random.nextInt(5000)); //以睡眠來模擬寫入數據操做 print(this+" 寫入數據完畢,等待其餘線程寫入完畢"+" "+System.currentTimeMillis()); barrier.await(); TimeUnit.MILLISECONDS.sleep(10); } catch (InterruptedException e) { print(this + "is interrupted!"); }catch(BrokenBarrierException e){ throw new RuntimeException(e); } print("全部任務寫入完畢,繼續處理其餘任務... "+System.currentTimeMillis()); } } @Override public String toString() { return getClass().getSimpleName()+"-"+id; } } class CyclicBarrierManager implements Runnable{ private CyclicBarrier barrier ; private ExecutorService exec; public CyclicBarrierManager(CyclicBarrier barrier, ExecutorService exec,int N){ this.barrier = barrier ; this.exec = exec; for (int i = 0; i < N-1; ++i){ exec.execute(new WriteTask(barrier)); } } @Override public void run(){ while (!Thread.interrupted()){ try { barrier.await(); }catch (InterruptedException e){ print(getClass().getSimpleName()+" 被中斷了!"); }catch (BrokenBarrierException e){ throw new RuntimeException(e); } } } } public class CyclicBarrierTest { public static void main(String[] args) throws Exception{ int N = 4; CyclicBarrier barrier = new CyclicBarrier(N); ExecutorService exec = Executors.newCachedThreadPool(); exec.execute(new CyclicBarrierManager(barrier,exec,N)); exec.shutdown(); } } #輸出結果: WriteTask-1 開始寫入數據... WriteTask-2 開始寫入數據... WriteTask-0 開始寫入數據... WriteTask-2 寫入數據完畢,等待其餘線程寫入完畢 1512051484365 WriteTask-0 寫入數據完畢,等待其餘線程寫入完畢 1512051485503 WriteTask-1 寫入數據完畢,等待其餘線程寫入完畢 1512051488068 全部任務寫入完畢,繼續處理其餘任務... 1512051488078 全部任務寫入完畢,繼續處理其餘任務... 1512051488078 WriteTask-2 開始寫入數據... 全部任務寫入完畢,繼續處理其餘任務... 1512051488078 WriteTask-1 開始寫入數據... WriteTask-0 開始寫入數據... WriteTask-0 寫入數據完畢,等待其餘線程寫入完畢 1512051488513 WriteTask-1 寫入數據完畢,等待其餘線程寫入完畢 1512051489045 WriteTask-2 寫入數據完畢,等待其餘線程寫入完畢 1512051489945 全部任務寫入完畢,繼續處理其餘任務... 1512051489955 WriteTask-0 開始寫入數據... 全部任務寫入完畢,繼續處理其餘任務... 1512051489955 全部任務寫入完畢,繼續處理其餘任務... 1512051489955 WriteTask-2 開始寫入數據... WriteTask-1 開始寫入數據... WriteTask-2 寫入數據完畢,等待其餘線程寫入完畢 1512051490155 WriteTask-1 寫入數據完畢,等待其餘線程寫入完畢 1512051494477 WriteTask-0 寫入數據完畢,等待其餘線程寫入完畢 1512051494823 全部任務寫入完畢,繼續處理其餘任務... 1512051494833 全部任務寫入完畢,繼續處理其餘任務... 1512051494833 WriteTask-0 開始寫入數據... 全部任務寫入完畢,繼續處理其餘任務... 1512051494833 WriteTask-1 開始寫入數據... WriteTask-2 開始寫入數據... WriteTask-2 寫入數據完畢,等待其餘線程寫入完畢 1512051494961 WriteTask-0 寫入數據完畢,等待其餘線程寫入完畢 1512051496040 WriteTask-1 寫入數據完畢,等待其餘線程寫入完畢 1512051498121 全部任務寫入完畢,繼續處理其餘任務... 1512051498132 全部任務寫入完畢,繼續處理其餘任務... 1512051498132 WriteTask-1 開始寫入數據... 全部任務寫入完畢,繼續處理其餘任務... 1512051498132
public Semaphore(int permits) { //參數permits表示許可數目,即同時能夠容許多少線程進行訪問 sync = new NonfairSync(permits); } public Semaphore(int permits, boolean fair) { //這個多了一個參數fair表示是不是公平的,即等待時間越久的越先獲取許可 sync = (fair)? new FairSync(permits) : new NonfairSync(permits); }
public void acquire() throws InterruptedException { } //獲取一個許可 public void acquire(int permits) throws InterruptedException { } //獲取permits個許可 public void release() {} //釋放一個許可 public void release(int permits) {} //釋放permits個許可
這4個方法都會被阻塞,若是想當即獲得執行結果,可使用下面幾個方法:ui
public boolean tryAcquire() { }; //嘗試獲取一個許可,若獲取成功,則當即返回true,若獲取失敗,則當即返回false public boolean tryAcquire(long timeout, TimeUnit unit) throws InterruptedException { }; //嘗試獲取一個許可,若在指定的時間內獲取成功,則當即返回true,不然則當即返回false public boolean tryAcquire(int permits) { }; //嘗試獲取permits個許可,若獲取成功,則當即返回true,若獲取失敗,則當即返回false public boolean tryAcquire(int permits, long timeout, TimeUnit unit) throws InterruptedException { }; //嘗試獲取permits個許可,若在指定的時間內獲取成功,則當即返回true,不然則當即返回false
package sychronized; import java.util.Random; import java.util.concurrent.*; import static net.mindview.util.Print.*; class Worker implements Runnable{ private static int count = 0; private final int id = count++; private int finished = 0; private Random random = new Random(47); private Semaphore semaphore; public Worker(Semaphore semaphore){ this.semaphore = semaphore; } @Override public void run(){ try { while (!Thread.interrupted()){ semaphore.acquire(); print(this+" 佔用一個機器在生產... "); TimeUnit.MILLISECONDS.sleep(random.nextInt(2000)); synchronized (this){ print(" 已經生產了"+(++finished)+"個產品,"+"釋放出機器"); } semaphore.release(); } } catch (InterruptedException e) { e.printStackTrace(); } } @Override public String toString() { return getClass().getSimpleName()+"-"+id; } } public class SemaphoreTest { public static void main(String[] args) { int N = 8; //工人數 Semaphore semaphore = new Semaphore(5); //機器數目 ExecutorService exec = Executors.newCachedThreadPool(); for (int i = 0; i < N; ++i){ exec.execute(new Worker(semaphore)); } exec.shutdown(); } }
CountDownLatch和CyclicBarrier都可以實現線程之間的等待,只不過它們側重點不一樣:this
Semaphore 其實和鎖有點相似,它通常用於控制對 某組 資源的訪問權限,而鎖是控制對 某個 資源的訪問權限。線程