CyclicBarrier使用:java
import java.util.Random; import java.util.concurrent.BrokenBarrierException; import java.util.concurrent.CyclicBarrier; /** * 三個運動員各自準備,等到三我的都準備好後,再一塊兒跑</br>@see 1:先建立一個公共 CyclicBarrier 對象,設置 同時等待 的線程數,CyclicBarrier cyclicBarrier = new CyclicBarrier(3);</br> 2:這些線程同時開始本身作準備,自身準備完畢後,須要等待別人準備完畢,這時調用 cyclicBarrier.await(); 便可開始等待別人;</br> 3:當指定的 同時等待 的線程數都調用了 cyclicBarrier.await();時,意味着這些線程都準備完畢好,而後這些線程才 同時繼續執行。</br> * */ public class TestCyclicBarrier { public static void main(String[] args) { int runner = 3; final CyclicBarrier cycliBarrier = new CyclicBarrier(runner); final Random random = new Random(); for (char runnerName = 'A'; runnerName <= 'C'; runnerName++) { final String rName = String.valueOf(runnerName); new Thread(new Runnable(){ @Override public void run() { long prepareTime = random.nextInt(10000)+100; System.out.println(rName + " is preparing for time: " + prepareTime); try { Thread.sleep(prepareTime); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(rName + " is prepared, waiting for others"); try { cycliBarrier.await(); // 當前運動員準備完畢,等待別人準備好 } catch (InterruptedException e) { e.printStackTrace(); } catch (BrokenBarrierException e) { e.printStackTrace(); } System.out.println(rName + " starts running"); // 全部運動員都準備好了,一塊兒開始跑 } }).start(); } } }
輸出:緩存
CountDownLatch例子dom
import java.util.concurrent.CountDownLatch; /** * 四個線程 A B C D,其中 D 要等到 A B C 全執行完畢後才執行,並且 A B C 是同步運行的@see 1:建立一個計數器,設置初始值,CountdownLatch countDownLatch = new CountDownLatch(2);</br> 2:在 等待線程 裏調用 countDownLatch.await() 方法,進入等待狀態,直到計數值變成 0;</br> 3:在 其餘線程 裏,調用 countDownLatch.countDown() 方法,該方法會將計數值減少 1;</br> 4:當 其餘線程 的 countDown() 方法把計數值變成 0 時,等待線程 裏的 countDownLatch.await() 當即退出,繼續執行下面的代碼。</br> * */ public class TestCountDownLatch { public static void main(String[] args) { int workerNum = 3; final CountDownLatch countDownlatch = new CountDownLatch(workerNum); new Thread(new Runnable(){ @Override public void run() { System.out.println("D is waiting for other three threads"); try { countDownlatch.await(); System.out.println("D is start work"); Thread.sleep(100); System.out.println("D finsh Work"); } catch (InterruptedException e) { e.printStackTrace(); } } }).start(); for (char threadName = 'A'; threadName <= 'C'; threadName++) { final String tName = String.valueOf(threadName); new Thread(new Runnable(){ @Override public void run() { System.out.println(tName + " is working"); try { Thread.sleep(100); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(tName + " finished"); countDownlatch.countDown(); } }).start(); } } }
輸出:ide
FutureTask、Callable例子spa
import java.util.concurrent.Callable; import java.util.concurrent.ExecutionException; import java.util.concurrent.FutureTask; /** * 咱們想讓子線程去計算從 1 加到 100,並把算出的結果返回到主線程</br> * @see * 如何把子線程的結果回傳回來呢?在 Java 裏,有一個類是配合 Callable 使用的:FutureTask,不過注意,它獲取結果的 get 方法會阻塞主線程。 * */ public class TestCallableAndFutureTask { public static void main(String[] args) { Callable<Integer> callAble = new Callable<Integer>() { @Override public Integer call() throws Exception { System.out.println("Task starts"); Thread.sleep(100); int result = 0; for (int i = 0; i <= 100; i++) { result += i; } System.out.println("Task finished and return result"); return result; } }; FutureTask<Integer> futureTask = new FutureTask<Integer>(callAble); new Thread(futureTask).start(); try { System.out.println("Before futureTask.get()"); System.out.println("Result: " + futureTask.get()); System.out.println("After futureTask.get()"); } catch (InterruptedException e) { e.printStackTrace(); } catch (ExecutionException e) { e.printStackTrace(); } } }
輸出:線程
thread.join() 例子3d
/** * 實現效果:線程B在線程A完成以後再執行 * thread.join() * */ public class TestThreadJoin { public static void main(String[] args) { demo1(); } private static void demo1() { final Thread A = new Thread(new Runnable(){ @Override public void run() { PrintNumber("A"); } }) ; Thread B = new Thread(new Runnable(){ @Override public void run() { System.out.println("B 開始等待A"); try { A.join(); } catch (InterruptedException e) { e.printStackTrace(); } PrintNumber("B"); } }) ; A.start(); B.start(); } private static void PrintNumber(String ThreadName) { int i = 0; while (i++ < 3) { try { Thread.sleep(100); } catch(InterruptedException e) { e.printStackTrace(); } System.out.println(ThreadName + " print: " + i); } } }
輸出:code
wait()、notify() 例子:對象
public class TestWaitAndnotify { public static void main(String[] args) { demo2(); } public static void demo2 () { final Object lock = new Object(); Thread A = new Thread(new Runnable(){ @Override public void run() { System.out.println("INFO: A 等待鎖 "); synchronized (lock) { System.out.println("INFO: A 獲得了鎖 lock"); System.out.println("A1"); try { System.out.println("INFO: A 準備進入等待狀態,放棄鎖 lock 的控制權 "); lock.wait();//掛起線程A 放棄鎖 lock 的控制權 } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("INFO: 有人喚醒了 A, A 從新得到鎖 lock"); System.out.println("A2"); System.out.println("A3"); } } }); Thread B = new Thread(new Runnable() { @Override public void run() { System.out.println("INFO: B 等待鎖 "); synchronized (lock) { System.out.println("INFO: B 獲得了鎖 lock"); System.out.println("B1"); System.out.println("B2"); System.out.println("B3"); System.out.println("INFO: B 打印完畢,調用 notify 方法 "); lock.notify(); // notify()方法喚醒正在等待lock鎖的線程A System.out.println("線程 B do notify method 完畢"); } } }); A.start(); B.start(); } }
輸出:blog
Condition 例子(生產消費):
import java.util.concurrent.locks.Condition; import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReentrantLock; public class TestCondition { public static void main(String[] args) { final BoundedBuffer b = new BoundedBuffer(); new Thread(new Runnable() { // 寫線程 public void run() { int i = 1; while (true) { try { b.put(i++); } catch (InterruptedException e) { e.printStackTrace(); } } } }).start(); new Thread(new Runnable() { // 讀線程 public void run() { while (true) { try { b.take(); } catch (InterruptedException e) { e.printStackTrace(); } } } }).start(); } } class BoundedBuffer{ final Lock lock = new ReentrantLock(); // 鎖對象 final Condition notFull = lock.newCondition(); // 寫線程條件 final Condition notEmpty = lock.newCondition(); // 讀線程條件 final Integer[] items = new Integer[10]; // 緩存隊列 int putptr; // 寫索引 int takeptr; // 讀索引 int count; // 隊列中存在的數據個數 public void put(Integer x) throws InterruptedException { lock.lock(); try { while(count == items.length) { // 若是隊列滿了 notFull.await(); // 阻塞寫線程 } items[putptr] = x; // 賦值 System.out.println("寫入:" + x); if(++putptr == items.length) { // 若是寫索引寫到隊列的最後一個位置了,那麼置爲0 putptr = 0; } ++count; // 個數++ notEmpty.signal(); // 喚醒讀線程 } finally { lock.unlock(); } } public Integer take() throws InterruptedException { lock.lock(); try { while(count == 0) { // 若是隊列爲空 notEmpty.await(); // 阻塞讀線程 } Integer x = items[takeptr]; // 取值 System.out.println("讀取:" + x); if(++takeptr == items.length) { // 若是讀索引讀到隊列的最後一個位置了,那麼置爲0 takeptr = 0; } --count; // 個數-- notFull.signal(); return x; } finally { lock.unlock(); } } }
輸出:
.......