假設一場短跑比賽,使用多個線程代表每個運動員的狀态和比賽過程,需要每個運動員同時出發,列印出每個關鍵節點的時間作為參考:
CountDownLatch
來自API文檔

所有方法
Modifier and Type | Method and Description |
---|---|
| 導緻目前線程等到鎖存器計數到零,除非線程是 interrupted 。 |
| 使目前線程等待直到鎖存器計數到零為止,除非線程為 interrupted或指定的等待時間過去。 |
| 減少鎖存器的計數,如果計數達到零,釋放所有等待的線程。 |
| 傳回目前計數。 |
| 傳回一個辨別此鎖存器的字元串及其狀态。 |
package com.muyi;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Random;
import java.util.concurrent.CountDownLatch;
/**
* @Author: muyi
* @Date: 2021/3/23 10:27
*/
public class Main {
final static SimpleDateFormat sdf=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
public static void main(String[] args) throws InterruptedException
{
CountDownLatch startLatch = new CountDownLatch(1);//控制比賽協作
CountDownLatch endLatch = new CountDownLatch(8);// 每個人的比賽程序
Runner run1 = new Runner(1,startLatch, endLatch);
Runner run2 = new Runner(2, startLatch,endLatch);
Runner run3 = new Runner(3, startLatch,endLatch);
Runner run4 = new Runner(4, startLatch,endLatch);
Runner run5 = new Runner(5, startLatch,endLatch);
Runner run6 = new Runner(6, startLatch,endLatch);
Runner run7 = new Runner(7, startLatch,endLatch);
Runner run8 = new Runner(8, startLatch,endLatch);
run1.start();
run2.start();
run3.start();
run4.start();
run5.start();
run6.start();
run7.start();
run8.start();
System.out.println("3秒鐘預備!");
Thread.sleep(3000);
System.out.println("起跑!"+sdf.format(new Date()));
startLatch.countDown(); //工作開始
endLatch.await();// 等待所有勞工完成工作
System.out.println("比賽完成 " + sdf.format(new Date()));
}
static class Runner extends Thread {
int no;
CountDownLatch startLatch;
CountDownLatch endLatch;
public Runner(int no, CountDownLatch startLatch,CountDownLatch endLatch) {
this.no = no;
this.startLatch=startLatch;
this.endLatch = endLatch;
}
@Override
public void run() {
try {
Random random = new Random(no);
Integer runTime = random.nextInt(5000)*2;
System.out.println("run "+no+"進入賽道,等待開始!預計用時:"+runTime+"ms");
startLatch.await(); //等待開始工作時間
System.out.println("run " + no + " 起跑時間 "+ sdf.format(new Date()));
Thread.sleep(runTime);
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
System.out.println("run " + no + " 到達終點時間 " + sdf.format(new Date())+";剩餘完成比賽人:"+(endLatch.getCount()-1));
// if(no == 1) { // code1
endLatch.countDown();// 完成比賽,計數器減一
// }
}
}
}
}
// out
3秒鐘預備!
run 5進入賽道,等待開始!預計用時:8974ms
run 1進入賽道,等待開始!預計用時:7970ms
run 8進入賽道,等待開始!預計用時:4728ms
run 7進入賽道,等待開始!預計用時:8472ms
run 4進入賽道,等待開始!預計用時:3724ms
run 2進入賽道,等待開始!預計用時:2216ms
run 3進入賽道,等待開始!預計用時:7468ms
run 6進入賽道,等待開始!預計用時:3222ms
起跑!2021-04-14 14:58:01
run 5 起跑時間 2021-04-14 14:58:01
run 1 起跑時間 2021-04-14 14:58:01
run 8 起跑時間 2021-04-14 14:58:01
run 4 起跑時間 2021-04-14 14:58:01
run 7 起跑時間 2021-04-14 14:58:01
run 3 起跑時間 2021-04-14 14:58:01
run 6 起跑時間 2021-04-14 14:58:01
run 2 起跑時間 2021-04-14 14:58:01
run 2 到達終點時間 2021-04-14 14:58:03;剩餘完成比賽人:7
run 6 到達終點時間 2021-04-14 14:58:04;剩餘完成比賽人:6
run 4 到達終點時間 2021-04-14 14:58:05;剩餘完成比賽人:5
run 8 到達終點時間 2021-04-14 14:58:06;剩餘完成比賽人:4
run 3 到達終點時間 2021-04-14 14:58:08;剩餘完成比賽人:3
run 1 到達終點時間 2021-04-14 14:58:09;剩餘完成比賽人:2
run 7 到達終點時間 2021-04-14 14:58:09;剩餘完成比賽人:1
run 5 到達終點時間 2021-04-14 14:58:10;剩餘完成比賽人:0
比賽完成 2021-04-14 14:58:10
通過上面的輸入結果得到:所有人同時起步,且詳細記錄了比賽結束的時間;
如果放開注釋code1,發現比賽無法結束,因為隻有run1正式通知了裁判組完成了比賽(endLatch.countDown());
3秒鐘預備!
run 7進入賽道,等待開始!預計用時:8472ms
run 8進入賽道,等待開始!預計用時:4728ms
run 5進入賽道,等待開始!預計用時:8974ms
run 4進入賽道,等待開始!預計用時:3724ms
run 2進入賽道,等待開始!預計用時:2216ms
run 6進入賽道,等待開始!預計用時:3222ms
run 1進入賽道,等待開始!預計用時:7970ms
run 3進入賽道,等待開始!預計用時:7468ms
起跑!2021-04-14 14:59:10
run 8 起跑時間 2021-04-14 14:59:10
run 5 起跑時間 2021-04-14 14:59:10
run 7 起跑時間 2021-04-14 14:59:10
run 4 起跑時間 2021-04-14 14:59:10
run 2 起跑時間 2021-04-14 14:59:10
run 3 起跑時間 2021-04-14 14:59:10
run 1 起跑時間 2021-04-14 14:59:10
run 6 起跑時間 2021-04-14 14:59:10
run 2 到達終點時間 2021-04-14 14:59:12;剩餘完成比賽人:7
run 6 到達終點時間 2021-04-14 14:59:13;剩餘完成比賽人:7
run 4 到達終點時間 2021-04-14 14:59:13;剩餘完成比賽人:7
run 8 到達終點時間 2021-04-14 14:59:14;剩餘完成比賽人:7
run 3 到達終點時間 2021-04-14 14:59:17;剩餘完成比賽人:7
run 1 到達終點時間 2021-04-14 14:59:18;剩餘完成比賽人:7
run 7 到達終點時間 2021-04-14 14:59:18;剩餘完成比賽人:6
run 5 到達終點時間 2021-04-14 14:59:19;剩餘完成比賽人:6
CyclicBarrier
所有方法
| 等待所有 parties已經在這個障礙上調用了 。 |
---|---|
| 等待所有 parties已經在此屏障上調用 ,或指定的等待時間過去。 |
| 傳回目前正在等待障礙的各方的數量。 |
| 傳回旅行這個障礙所需的聚會數量。 |
| 查詢這個障礙是否處于破碎狀态。 |
| 将屏障重置為初始狀态。 |
CyclicBarrier有兩個構造方法:
CyclicBarrier(int parties)
建立一個新的 CyclicBarrier ,當給定數量的線程(線程)等待它時,它将跳閘,并且當屏障跳閘時不執行預定義的動作。
package com.muyi;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Random;
import java.util.concurrent.BrokenBarrierException;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.CyclicBarrier;
/**
* @Author: muyi
* @Date: 2021/3/23 10:27
*/
public class Main {
final static SimpleDateFormat sdf=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
public static void main(String[] args) throws InterruptedException
{
CyclicBarrier cyclicBarrier = new CyclicBarrier(8);
Runner run1 = new Runner(1, cyclicBarrier);
Runner run2 = new Runner(2, cyclicBarrier);
Runner run3 = new Runner(3, cyclicBarrier);
Runner run4 = new Runner(4, cyclicBarrier);
Runner run5 = new Runner(5, cyclicBarrier);
Runner run6 = new Runner(6, cyclicBarrier);
Runner run7 = new Runner(7, cyclicBarrier);
Runner run8 = new Runner(8, cyclicBarrier);
run1.start();
run2.start();
run3.start();
run4.start();
run5.start();
run6.start();
run7.start();
run8.start();
}
static class Runner extends Thread {
int no;
CyclicBarrier cyclicBarrier;
public Runner(int no, CyclicBarrier cyclicBarrier) {
this.no = no;
this.cyclicBarrier=cyclicBarrier;
}
@Override
public void run() {
try {
Random random = new Random(no);
Integer runTime = random.nextInt(5000)*2;
Thread.sleep(runTime/10);// 放大線程準備時間
System.out.println("run "+no+"進入賽道,等待開始!預計用時:"+runTime+"ms,準備完成人數:"+(cyclicBarrier.getNumberWaiting()+1));
cyclicBarrier.await();
System.out.println("run " + no + " 起跑時間 "+ sdf.format(new Date()));
Thread.sleep(runTime);
System.out.println("run " + no + " 預計到達終點時間 " + sdf.format(new Date())+";完成比賽人數:"+(cyclicBarrier.getNumberWaiting()+1));
cyclicBarrier.await();
System.out.println("全部完成 " + sdf.format(new Date()));
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
// out
run 2進入賽道,等待開始!預計用時:2216ms,準備完成人數:1
run 6進入賽道,等待開始!預計用時:3222ms,準備完成人數:2
run 4進入賽道,等待開始!預計用時:3724ms,準備完成人數:3
run 8進入賽道,等待開始!預計用時:4728ms,準備完成人數:4
run 3進入賽道,等待開始!預計用時:7468ms,準備完成人數:5
run 1進入賽道,等待開始!預計用時:7970ms,準備完成人數:6
run 7進入賽道,等待開始!預計用時:8472ms,準備完成人數:7
run 5進入賽道,等待開始!預計用時:8974ms,準備完成人數:8
run 1 起跑時間 2021-04-14 14:53:31
run 2 起跑時間 2021-04-14 14:53:31
run 4 起跑時間 2021-04-14 14:53:31
run 3 起跑時間 2021-04-14 14:53:31
run 8 起跑時間 2021-04-14 14:53:31
run 5 起跑時間 2021-04-14 14:53:31
run 7 起跑時間 2021-04-14 14:53:31
run 6 起跑時間 2021-04-14 14:53:31
run 2 預計到達終點時間 2021-04-14 14:53:33;完成比賽人數:1
run 6 預計到達終點時間 2021-04-14 14:53:34;完成比賽人數:2
run 4 預計到達終點時間 2021-04-14 14:53:34;完成比賽人數:3
run 8 預計到達終點時間 2021-04-14 14:53:35;完成比賽人數:4
run 3 預計到達終點時間 2021-04-14 14:53:38;完成比賽人數:5
run 1 預計到達終點時間 2021-04-14 14:53:39;完成比賽人數:6
run 7 預計到達終點時間 2021-04-14 14:53:39;完成比賽人數:7
run 5 預計到達終點時間 2021-04-14 14:53:40;完成比賽人數:8
全部完成 2021-04-14 14:53:40
全部完成 2021-04-14 14:53:40
全部完成 2021-04-14 14:53:40
全部完成 2021-04-14 14:53:40
全部完成 2021-04-14 14:53:40
全部完成 2021-04-14 14:53:40
全部完成 2021-04-14 14:53:40
全部完成 2021-04-14 14:53:40
Process finished with exit code 0
CyclicBarrier(int parties, Runnable barrierAction)
建立一個新的 CyclicBarrier ,當給定數量的線程(線程)等待時,它将跳閘,當屏障跳閘時執行給定的屏障動作,由最後一個進入屏障的線程執行。
package com.muyi;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Random;
import java.util.concurrent.BrokenBarrierException;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.CyclicBarrier;
/**
* @Author: muyi
* @Date: 2021/3/23 10:27
*/
public class Main {
final static SimpleDateFormat sdf=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
public static void main(String[] args) throws InterruptedException
{
CyclicBarrier cyclicBarrier = new CyclicBarrier(8,new Runnable(){
@Override
public void run() {
System.out.println("********裁判組記錄,發令***********");
System.out.println(sdf.format(new Date()));
}
});
Runner run1 = new Runner(1, cyclicBarrier);
Runner run2 = new Runner(2, cyclicBarrier);
Runner run3 = new Runner(3, cyclicBarrier);
Runner run4 = new Runner(4, cyclicBarrier);
Runner run5 = new Runner(5, cyclicBarrier);
Runner run6 = new Runner(6, cyclicBarrier);
Runner run7 = new Runner(7, cyclicBarrier);
Runner run8 = new Runner(8, cyclicBarrier);
run1.start();
run2.start();
run3.start();
run4.start();
run5.start();
run6.start();
run7.start();
run8.start();
}
static class Runner extends Thread {
int no;
CyclicBarrier cyclicBarrier;
public Runner(int no, CyclicBarrier cyclicBarrier) {
this.no = no;
this.cyclicBarrier=cyclicBarrier;
}
@Override
public void run() {
try {
Random random = new Random(no);
Integer runTime = random.nextInt(5000)*2;
Thread.sleep(runTime/10);// 放大線程準備時間
System.out.println("run "+no+"進入賽道,等待開始!預計用時:"+runTime+"ms,準備完成人數:"+(cyclicBarrier.getNumberWaiting()+1));
cyclicBarrier.await();
System.out.println("run " + no + " 起跑時間 "+ sdf.format(new Date()));
Thread.sleep(runTime);
System.out.println("run " + no + " 預計到達終點時間 " + sdf.format(new Date())+";完成比賽人數:"+(cyclicBarrier.getNumberWaiting()+1));
cyclicBarrier.await();
System.out.println("全部完成 " + sdf.format(new Date()));
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
//out
run 2進入賽道,等待開始!預計用時:2216ms,準備完成人數:1
run 6進入賽道,等待開始!預計用時:3222ms,準備完成人數:2
run 4進入賽道,等待開始!預計用時:3724ms,準備完成人數:3
run 8進入賽道,等待開始!預計用時:4728ms,準備完成人數:4
run 3進入賽道,等待開始!預計用時:7468ms,準備完成人數:5
run 1進入賽道,等待開始!預計用時:7970ms,準備完成人數:6
run 7進入賽道,等待開始!預計用時:8472ms,準備完成人數:7
run 5進入賽道,等待開始!預計用時:8974ms,準備完成人數:8
********裁判組記錄,發令***********
2021-04-14 14:55:54
run 5 起跑時間 2021-04-14 14:55:54
run 2 起跑時間 2021-04-14 14:55:54
run 4 起跑時間 2021-04-14 14:55:54
run 3 起跑時間 2021-04-14 14:55:54
run 7 起跑時間 2021-04-14 14:55:54
run 6 起跑時間 2021-04-14 14:55:54
run 1 起跑時間 2021-04-14 14:55:54
run 8 起跑時間 2021-04-14 14:55:54
run 2 預計到達終點時間 2021-04-14 14:55:56;完成比賽人數:1
run 6 預計到達終點時間 2021-04-14 14:55:57;完成比賽人數:2
run 4 預計到達終點時間 2021-04-14 14:55:58;完成比賽人數:3
run 8 預計到達終點時間 2021-04-14 14:55:59;完成比賽人數:4
run 3 預計到達終點時間 2021-04-14 14:56:02;完成比賽人數:5
run 1 預計到達終點時間 2021-04-14 14:56:02;完成比賽人數:6
run 7 預計到達終點時間 2021-04-14 14:56:03;完成比賽人數:7
run 5 預計到達終點時間 2021-04-14 14:56:03;完成比賽人數:8
********裁判組記錄,發令***********
2021-04-14 14:56:03
全部完成 2021-04-14 14:56:03
全部完成 2021-04-14 14:56:03
全部完成 2021-04-14 14:56:03
全部完成 2021-04-14 14:56:03
全部完成 2021-04-14 14:56:03
全部完成 2021-04-14 14:56:03
全部完成 2021-04-14 14:56:03
全部完成 2021-04-14 14:56:03