筆者是廣州的java程序員,剛畢業半年,工做之餘寫博客,若是以爲個人文章寫得不錯,能夠關注個人微信公衆號(J2彬彬),裏面會有更多精彩內容。從2018年8月份開始寫博客,但願往後寫出更多通俗易懂的技術文章與你們一同分享。java
talk is cheap,show me the code程序員
JUC實際上是屬於線程知識的中高級部分,因此也是面試中面試官喜歡問的一塊知識點,這塊知識也能比較看出一個程序員的功底,今天筆者就跟你們講講CountDownLatch,CyclicBarrier,Semaphore這些知識點。你們在看到這些知識的時候,千萬不要一上來就摳細節,首先應該弄明白這些知識點時是幹什麼用的,用來解決什麼問題,適合應用於什麼樣的業務場景。若是這些東西都沒搞清楚就學,那麼你學完很快就會忘掉。面試
以前筆者也發過一些關於JUC方面的知識,但也就是一些Demo代碼,並無細究,今天就是帶領你們:入虎穴,得虎子。微信
若是把多個線程比喻成運動員,CountDownLatch至關於槍聲發令員,槍聲未響,全部線程都處於等待狀態,當CountDownLatch計數器變爲0時
至關於槍聲發出,這時全部線程一同奔跑。與集齊七顆龍珠即可召喚神龍有殊途同歸之妙。多線程
1package com.bingo.thread.juc;
2
3/**
4 * Created with IntelliJ IDEA.
5 * Description: 倒時計數器(也叫閉鎖)
6 * User: bingo
7 * Date: 2018-11-25
8 * Time: 11:16
9 */
10import java.util.concurrent.CountDownLatch;
11import java.util.concurrent.ExecutorService;
12import java.util.concurrent.Executors;
13
14public class CountDownLatchDemo {
15
16 public static void main(String[]args) throws InterruptedException{
17 final CountDownLatch startGate=new CountDownLatch(1);
18 final CountDownLatch endGate=new CountDownLatch(5);
19 //線程池
20 ExecutorService exce=Executors.newCachedThreadPool();
21 //建立5個線程
22 for(int i=1;i<=5;i++){
23 final int num=i;
24 Thread thread =new Thread(new Runnable() {
25 public void run() {
26 try {
27 System.out.println(num+"號選手準備就緒,等待裁判員哨聲響起..");
28 //至關於同步鎖Synchronized中的await()方法
29 startGate.await();
30 try {
31 Thread.sleep((long) (Math.random()*10000));
32 } catch (InterruptedException e) {
33 e.printStackTrace();
34 }
35 System.out.println(num+"號選手到達終點..");
36 } catch (InterruptedException e) {
37 e.printStackTrace();
38 }
39 finally{
40 //至關於同步鎖Synchronized中的notify()方法,區別在於countDown須要執行5次後才能喚醒await()
41 endGate.countDown();
42 }
43 }
44 });
45 exce.execute(thread);
46 }
47 long start=System.nanoTime();
48 System.out.println("裁判員哨聲響起..");
49 Thread.sleep(10000);
50 //喚醒執行startGate.await()的線程,讓線程往下執行
51 startGate.countDown();
52 //等待被喚醒,主程序才能繼續往下執行,線程中每次執行endGate.countDown()就減1,當爲零的時候,主程序往下執行
53 endGate.await();
54 long end=System.nanoTime();
55 System.out.println("全部運動員到達終點,耗時:"+(end-start));
56 //關閉線程池
57 exce.shutdown();
58 }
59}
複製代碼
1裁判員哨聲響起..
21號選手準備就緒,等待裁判員哨聲響起..
32號選手準備就緒,等待裁判員哨聲響起..
43號選手準備就緒,等待裁判員哨聲響起..
54號選手準備就緒,等待裁判員哨聲響起..
65號選手準備就緒,等待裁判員哨聲響起..
73號選手到達終點..
81號選手到達終點..
94號選手到達終點..
105號選手到達終點..
112號選手到達終點..
12全部運動員到達終點,耗時:17708083042
13
14Process finished with exit code 0
複製代碼
CyclicBarrier與CountDownLatch很是類似,可是仍是有必定區別。咱們先看代碼。app
需求:人們(線程)前後到達餐桌上(某個點),可是不能動筷子(等待),全部人到齊才能夠吃年夜飯(線程到齊才能一同執行)dom
1package com.bingo.thread.juc;
2
3import java.util.concurrent.BrokenBarrierException;
4import java.util.concurrent.CyclicBarrier;
5
6public class CyclicBarrierDemo {
7
8 public static void main(String[] args) {
9 final int count = 5;
10 final CyclicBarrier barrier = new CyclicBarrier(count, new Runnable() {
11 @Override
12 public void run() {
13 System.out.println("人到齊,你們一塊兒吃年夜飯!");
14 }
15 });
16
17 // they do not have to start at the same time...
18 for (int i = 0; i < count; i++) {
19 new Thread(new Worker(i, barrier)).start();
20 }
21 }
22}
23
24class Worker implements Runnable {
25 final int id;
26 final CyclicBarrier barrier;
27
28 public Worker(final int id, final CyclicBarrier barrier) {
29 this.id = id;
30 this.barrier = barrier;
31 }
32
33 @Override
34 public void run() {
35 try {
36 System.out.println(this.id + "starts to run !");
37 Thread.sleep((long) (Math.random() * 10000));
38 System.out.println(this.id + "到桌 !");
39 this.barrier.await();
40 } catch (InterruptedException e) {
41 e.printStackTrace();
42 } catch (BrokenBarrierException e) {
43 e.printStackTrace();
44 }
45 }
46}
複製代碼
10starts to run !
22starts to run !
31starts to run !
43starts to run !
54starts to run !
64到桌 !
73到桌 !
81到桌 !
92到桌 !
100到桌 !
11人到齊,你們一塊兒吃年夜飯!
12
13Process finished with exit code 0
複製代碼
Semaphore與鎖相似,可是與鎖不一樣的是,Synchronized是獨佔式的,同一時刻只有一個線程可以操做資源,而Semaphore容許指定的多個線程同時操做同個資源。它經過獲取許可,釋放許可來控制多個線程操做資源。ide
需求:假如如今網吧有5臺電腦,可是如今有8我的進入網吧,同一時間只能有5我的上機,而其中三我的主要等到其餘人空出電腦的時候才能上機。
這時Semaphore就派上用場了。學習
1package com.bingo.thread.juc;
2
3import java.util.concurrent.Semaphore;
4
5public class SemaphoreDemo {
6 public static void main(String[] args) {
7 int N = 8; //學生數
8 Semaphore semaphore = new Semaphore(5); //電腦數目
9 for(int i=0;i<N;i++)
10 new Worker(i,semaphore).start();
11 }
12
13 static class Worker extends Thread{
14 private int num;
15 private Semaphore semaphore;
16 public Worker(int num,Semaphore semaphore){
17 this.num = num;
18 this.semaphore = semaphore;
19 }
20
21 @Override
22 public void run() {
23 try {
24 semaphore.acquire();
25 System.out.println("同窗"+this.num+"佔用一臺電腦...");
26 Thread.sleep(2000);
27 System.out.println("--同窗"+this.num+"離開電腦");
28 semaphore.release();
29 } catch (InterruptedException e) {
30 e.printStackTrace();
31 }
32 }
33 }
34}
複製代碼
1同窗0佔用一臺電腦...
2同窗1佔用一臺電腦...
3同窗2佔用一臺電腦...
4同窗3佔用一臺電腦...
5同窗4佔用一臺電腦...
6--同窗0離開電腦
7--同窗1離開電腦
8--同窗4離開電腦
9--同窗3離開電腦
10同窗7佔用一臺電腦...
11--同窗2離開電腦
12同窗6佔用一臺電腦...
13同窗5佔用一臺電腦...
14--同窗7離開電腦
15--同窗5離開電腦
16--同窗6離開電腦
17
18Process finished with exit code 0
複製代碼
多線程是java面試中很是重要一環,算是重點和難點吧,特別是須要結合JVM一塊兒學習,因此從此筆者還會繼續推出相關博客文章,也但願讀者耐心等待。測試