這三個(gè)類都是基于AQS實(shí)現(xiàn)的類,也是面試中??嫉念?,今天我們來學(xué)習(xí)一下這三個(gè)類的用法。
- CountDownLatch:
Count:數(shù)數(shù)
Down:向下
Latch:門閂
顧名思義,這個(gè)類就是用來“倒計(jì)時(shí)”的,可以用來讓一個(gè)線程或多個(gè)線程等待多個(gè)線程。
下面看例子:
這個(gè)例子模擬的是同學(xué)下晚自習(xí)后,班長(zhǎng)關(guān)門的事件。正常情況是等所有同學(xué)都走完之后,然后班長(zhǎng)鎖門,離開教室。這里新建五個(gè)線程模擬同學(xué),主線程代表班長(zhǎng)。
public class Test {
public static void main(String[] args) {
for (int i = 1; i <= 5; i++) {
new Thread(()->{
System.out.println(Thread.currentThread().getName() + "\t同學(xué)離開教室");
},String.valueOf(i)).start();
}
System.out.println(Thread.currentThread().getName() + "班長(zhǎng)離開教室,鎖門");
}
}
1 同學(xué)離開教室
2 同學(xué)離開教室
3 同學(xué)離開教室
4 同學(xué)離開教室
main班長(zhǎng)離開教室,鎖門
5 同學(xué)離開教室
可以看到還剩一位同學(xué)沒走,班長(zhǎng)就把門鎖上了,這肯定是不行的,我們來用CountDownLatch來解決這個(gè)問題。
import java.util.concurrent.CountDownLatch;
public class Test {
public static void main(String[] args) throws InterruptedException {
CountDownLatch countDownLatch = new CountDownLatch(5);//設(shè)置初始門閂值,模擬還有五個(gè)同學(xué)在教室
for (int i = 1; i <= 5; i++) {
new Thread(()->{
System.out.println(Thread.currentThread().getName() + "\t同學(xué)離開教室");
countDownLatch.countDown();//每有一個(gè)同學(xué)離開教室,門閂的值就減1
},String.valueOf(i)).start();
}
countDownLatch.await();//門閂的值減到0之前,main線程阻塞
System.out.println(Thread.currentThread().getName() + "班長(zhǎng)離開教室,鎖門");
}
}
1 同學(xué)離開教室
2 同學(xué)離開教室
3 同學(xué)離開教室
4 同學(xué)離開教室
5 同學(xué)離開教室
main班長(zhǎng)離開教室,鎖門
再無論怎么運(yùn)行,main線程一定會(huì)等五個(gè)線程都運(yùn)行之后才會(huì)輸出。
-
CyclicBarrier
用來控制多個(gè)線程互相等待,只有所有線程全部到達(dá)后,這些線程才會(huì)繼續(xù)執(zhí)行。
CyclicBarrier有兩個(gè)構(gòu)造方法:public CyclicBarrier(int parties){ }public CyclicBarrier(int parties,Runnable barrierAction){ }當(dāng)所有的線程都到達(dá)時(shí),會(huì)觸發(fā)barrierAction
import java.util.concurrent.BrokenBarrierException;
import java.util.concurrent.CyclicBarrier;
public class Test {
public static void main(String[] args) {
CyclicBarrier cyclicBarrier = new CyclicBarrier(7,new Thread(()-> {
System.out.println("召喚神龍");
}));//等待七個(gè)線程到位之后,執(zhí)行"System.out.println("召喚神龍");" 任務(wù)。
for (int i = 1; i <= 7; i++) {
new Thread(()->{
System.out.println(Thread.currentThread().getName() + "顆龍珠已經(jīng)收集");
try {
cyclicBarrier.await();//設(shè)置屏障,等待所有線程到位
} catch (InterruptedException e) {
e.printStackTrace();
} catch (BrokenBarrierException e) {
e.printStackTrace();
}
},String.valueOf(i)).start();
}
}
}
- semaphore
中文名:信號(hào)量,用于控制多個(gè)線程對(duì)互斥資源的訪問控制。
import java.util.concurrent.Semaphore;
import java.util.concurrent.TimeUnit;
public class Test {
public static void main(String[] args) {
Semaphore semaphore = new Semaphore(3); // 模擬總共有三個(gè)車位
/*
用六個(gè)線程來模擬有六輛車要搶占三個(gè)車位
*/
for (int i = 1; i <= 6; i++) {
new Thread(() -> {
try {
semaphore.acquire(); //搶占資源
System.out.println(Thread.currentThread().getName() + "\t搶到車位");
TimeUnit.SECONDS.sleep(3);
System.out.println(Thread.currentThread().getName() + "\t等待三秒后離開車位");
} catch (InterruptedException e) {
e.printStackTrace();
}finally {
semaphore.release();//釋放資源
}
},String.valueOf(i)).start();
}
}
}
1 搶到車位
2 搶到車位
3 搶到車位
2 等待三秒后離開車位
3 等待三秒后離開車位
1 等待三秒后離開車位
4 搶到車位
6 搶到車位
5 搶到車位
4 等待三秒后離開車位
6 等待三秒后離開車位
5 等待三秒后離開車位