Java多線程與併發_同步工具類CountDownLatch,CyclicBarrier和Semaphore
人處在一種默默奮鬥的狀態,精神就會從瑣碎生活中得到昇華
一、CountDownLatch
構造器
- CountDownLatch(int count) //參數count爲計數值
主要方法:
- await():調用await()方法的線程會被掛起,它會等待直到count值爲0才繼續執行
- await(long timeout,TimeUnit unit):和await()類似,只不過等待一定的時間後count值還沒變爲0的話就會繼續執行
- countDown():將count值減1
例子說明:秦滅6國,一統華夏
- 解釋:6個國家陸續被滅後,秦國最後才一統華夏
- main主線程必須要等前面6個線程完成全部工作後,自己才能開幹
public class CountDownLatchDemo {
public static void main(String[] args) throws InterruptedException {
//秦滅6國,一統華夏
CountDownLatch countDownLatch = new CountDownLatch(6);
for (int i = 0; i < 6; i++) {
new Thread(() -> {
System.out.println(Thread.currentThread().getName() + "\t 國被滅");
countDownLatch.countDown();
},CountryEnums.forEachCountryEnums(i).getRetMsg()).start();
}
countDownLatch.await();
System.out.println("-------main 秦滅6國,一統華夏");
}
}
國家的枚舉類
public enum CountryEnums {
ONE(0,"韓"),
TWO(1,"魏"),
THREE(2,"趙"),
FOUR(3,"齊"),
FIVE(4,"楚"),
SIX(5,"燕")
;
private Integer retCode;
private String retMsg;
CountryEnums(Integer retCode, String retMsg) {
this.retCode = retCode;
this.retMsg = retMsg;
}
public Integer getRetCode() {
return retCode;
}
public void setRetCode(Integer retCode) {
this.retCode = retCode;
}
public String getRetMsg() {
return retMsg;
}
public void setRetMsg(String retMsg) {
this.retMsg = retMsg;
}
public static CountryEnums forEachCountryEnums(Integer index) {
for (CountryEnums element : values()) {
if (element.getRetCode() == index) {
return element;
}
}
return null;
}
}
結果
韓 國被滅
齊 國被滅
趙 國被滅
魏 國被滅
楚 國被滅
燕 國被滅
-------main 秦滅6國,一統華夏
Process finished with exit code 0
二、CyclicBarrier
字面意思是可循環(Cyclic)使用的屏障(Barrier),他要做的事情是,
讓一組線程到達一個屏障(也可以叫同步點)時被阻塞,
直到最後一個線程到達屏障時,屏障纔會開門,所有被屏障攔截的線程纔會繼續幹活。
線程進入屏障通過CyclicBarrier的await()方法
構造器
- CyclicBarrier(int parties, Runnable barrierAction)
- CyclicBarrier(int parties)
參數parties指讓多少個線程或者任務等待至barrier狀態;參數barrierAction爲當這些線程都達到barrier狀態時會執行的內容。
主要方法
- int await()
- int await(long timeout, TimeUnit unit)
第一個版本比較常用,用來掛起當前線程,直至所有線程都到達barrier狀態再同時執行後續任務;
第二個版本是讓這些線程等待至一定的時間,如果還有線程沒有到達barrier狀態就直接讓到達barrier的線程執行後續任務。
例子說明:集齊7顆龍珠召喚神龍
public class CyclicBarrierDemo {
private static final int NUMBER = 7;
public static void main(String[] args) {
CyclicBarrier cyclicBarrier = new CyclicBarrier(NUMBER,() -> {
System.out.println("*****召喚神龍*****");
});
for (int i = 1; i <= NUMBER; i++) {
int tempInt = i;
new Thread(() -> {
System.out.println(Thread.currentThread().getName() + "\t 收集到第" + tempInt + "\t 顆龍珠");
try {
cyclicBarrier.await();
} catch (Exception e) {
e.printStackTrace();
}
},String.valueOf(i)).start();
}
}
}
結果
1 收集到第1 顆龍珠
4 收集到第4 顆龍珠
3 收集到第3 顆龍珠
2 收集到第2 顆龍珠
5 收集到第5 顆龍珠
6 收集到第6 顆龍珠
7 收集到第7 顆龍珠
*****召喚神龍*****
Process finished with exit code 0
三、Semaphore
Semaphore(信號量)是用來控制同時訪問特定資源的線程數量,它通過協調各個線程,以保證合理的使用公共資源。
public class SemaphoreDemo {
public static void main(String[] args) {
Semaphore semaphore = new Semaphore(3);//模擬3個停車位
for (int i = 1; i <= 6; i++) {//模擬6部汽車
new Thread(() -> {
try {
semaphore.acquire();
System.out.println(Thread.currentThread().getName() + "\t 搶佔了車位");
TimeUnit.SECONDS.sleep(new Random().nextInt(8));
System.out.println(Thread.currentThread().getName() + "\t 離開了車位");
} catch (InterruptedException e) {
e.printStackTrace();
}finally {
semaphore.release();
}
},String.valueOf(i)).start();
}
}
}
結果:
1 搶佔了車位
3 搶佔了車位
2 搶佔了車位
2 離開了車位
3 離開了車位
4 搶佔了車位
5 搶佔了車位
1 離開了車位
6 搶佔了車位
4 離開了車位
5 離開了車位
6 離開了車位
Process finished with exit code 0