一区二区三区在线-一区二区三区亚洲视频-一区二区三区亚洲-一区二区三区午夜-一区二区三区四区在线视频-一区二区三区四区在线免费观看

服務(wù)器之家:專注于服務(wù)器技術(shù)及軟件下載分享
分類導(dǎo)航

PHP教程|ASP.NET教程|Java教程|ASP教程|編程技術(shù)|正則表達(dá)式|C/C++|IOS|C#|Swift|Android|VB|R語言|JavaScript|易語言|vb.net|

服務(wù)器之家 - 編程語言 - Java教程 - java線程間通訊的一些方法總結(jié)

java線程間通訊的一些方法總結(jié)

2021-08-04 10:26負(fù)債程序猿 Java教程

這篇文章主要介紹了java線程間通訊的一些方法,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧

前言

并發(fā)編程中,我們可能會(huì)遇到這樣一個(gè)場(chǎng)景

A、B兩個(gè)線程并行,但是我希望保證B線程在A線程執(zhí)行完了后再執(zhí)行

這個(gè)時(shí)候就需要線程間進(jìn)行通訊

A執(zhí)行完了后對(duì)B說一聲,喂B,我執(zhí)行完了

來康康用Java怎么實(shí)現(xiàn)

1、基于synchronized

2、基于reentrantLock

3、基于volatile

4、基于countDownLatch

我目前就知道這四種

1、synchronized+wait() 和 notify()

wait() 和 notify()都是Object類的通訊方法,注意一點(diǎn),wait和 notify必須搭配synchronized使用,并且wait()會(huì)釋放鎖,notify()不會(huì)釋放鎖

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
public class SynchronizedTest {
 
 //定義個(gè)year,用來記錄某明星的練習(xí)年數(shù)
 private static double year;
 
 public void run() {
  //線程A,練習(xí)唱跳rap
  Thread threadA = new Thread(() -> {
   synchronized (this) {
    for (year = 0.5; year <= 5; year += 0.5) {
     System.out.println("蔡徐雞開始練習(xí)唱跳rap:已練習(xí)" + year + "年");
     try {
      Thread.sleep(288);
     } catch (InterruptedException e) {
      e.printStackTrace();
     }
     //眾所周知,練習(xí)兩年半即可出道
     if (year == 2.5) {
      System.out.println("===========================>成功練習(xí)兩年半,出道!!!");
      this.notify();
     }
    }
   }
  });
  //線程B,練習(xí)打籃球
  Thread threadB = new Thread(() -> {
   while (true) {
    synchronized (this) {
     try {
      this.wait();
     } catch (InterruptedException e) {
      e.printStackTrace();
     }
     System.out.println("蔡徐雞開始練習(xí)打籃球");
    }
   }
  });
  //注意,一定要先啟動(dòng)B,不然會(huì)導(dǎo)致B永遠(yuǎn)拿不到鎖
  threadB.start();
  threadA.start();
 }
 
 public static void main(String[] args) {
  SynchronizedTest test = new SynchronizedTest();
  test.run();
 }
}

運(yùn)行結(jié)果:

蔡徐雞開始練習(xí)唱跳rap:已練習(xí)0.5年
蔡徐雞開始練習(xí)唱跳rap:已練習(xí)1.0年
蔡徐雞開始練習(xí)唱跳rap:已練習(xí)1.5年
蔡徐雞開始練習(xí)唱跳rap:已練習(xí)2.0年
蔡徐雞開始練習(xí)唱跳rap:已練習(xí)2.5年
===========================>成功練習(xí)兩年半,出道!!!
蔡徐雞開始練習(xí)唱跳rap:已練習(xí)3.0年
蔡徐雞開始練習(xí)唱跳rap:已練習(xí)3.5年
蔡徐雞開始練習(xí)唱跳rap:已練習(xí)4.0年
蔡徐雞開始練習(xí)唱跳rap:已練習(xí)4.5年
蔡徐雞開始練習(xí)唱跳rap:已練習(xí)5.0年
蔡徐雞開始練習(xí)打籃球

注意看運(yùn)行結(jié)果,線程A在執(zhí)行notify后并沒有釋放鎖,而是執(zhí)行完當(dāng)前任務(wù)才開始執(zhí)行線程B的任務(wù)

2、基于ReentrantLock

ReentrantLock也能實(shí)現(xiàn)線程間通訊,不過有點(diǎn)麻煩,需要結(jié)合ReentrantLock的Condition

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
public class LockTest {
  //定義個(gè)year,用來記錄某明星練習(xí)打籃球的年數(shù)
  private static double year;
 
  public static void main(String[] args) {
   ReentrantLock lock = new ReentrantLock();
   Condition condition = lock.newCondition();
   //線程A,練習(xí)唱跳rap
   Thread threadA = new Thread(() -> {
    //執(zhí)行業(yè)務(wù)代碼前上鎖
    lock.lock();
    for (year = 0.5; year <= 5; year += 0.5) {
     System.out.println("蔡徐雞開始練習(xí)唱跳rap:已練習(xí)" + year + "年");
     try {
      Thread.sleep(288);
     } catch (InterruptedException e) {
      e.printStackTrace();
     }
     //眾所周知,練習(xí)兩年半即可出道
     if (year == 2.5) {
      System.out.println("===========================>成功練習(xí)兩年半,出道!!!");
      //喚醒等待中的線程
      condition.signal();
     }
    }
    //業(yè)務(wù)代碼執(zhí)行完后解鎖
    lock.unlock();
   });
   //線程B,練習(xí)打籃球
   Thread threadB = new Thread(() -> {
    //執(zhí)行業(yè)務(wù)代碼前上鎖
    lock.lock();
    while (true) {
     try {
      //讓線程等待,如果計(jì)數(shù)器為0的話,則立即執(zhí)行
      condition.await();
     } catch (InterruptedException e) {
      e.printStackTrace();
     }
     System.out.println("蔡徐老母雞開始練習(xí)打籃球");
     break;
    }
    //業(yè)務(wù)代碼執(zhí)行完后解鎖
    lock.unlock();
   });
   //注意,一定要先啟動(dòng)B,不然會(huì)導(dǎo)致B永遠(yuǎn)拿不到鎖
   threadB.start();
   threadA.start();
  }
 }

運(yùn)行結(jié)果:

蔡徐雞開始練習(xí)唱跳rap:已練習(xí)0.5年
蔡徐雞開始練習(xí)唱跳rap:已練習(xí)1.0年
蔡徐雞開始練習(xí)唱跳rap:已練習(xí)1.5年
蔡徐雞開始練習(xí)唱跳rap:已練習(xí)2.0年
蔡徐雞開始練習(xí)唱跳rap:已練習(xí)2.5年
===========================>成功練習(xí)兩年半,出道!!!
蔡徐雞開始練習(xí)唱跳rap:已練習(xí)3.0年
蔡徐雞開始練習(xí)唱跳rap:已練習(xí)3.5年
蔡徐雞開始練習(xí)唱跳rap:已練習(xí)4.0年
蔡徐雞開始練習(xí)唱跳rap:已練習(xí)4.5年
蔡徐雞開始練習(xí)唱跳rap:已練習(xí)5.0年
蔡徐老母雞開始練習(xí)打籃球

效果和synchronized+wait() 和 notify()一樣一樣的

3、基于volatile

使用共享變量也能實(shí)現(xiàn),用volatile即可,原理就是多個(gè)線程共同監(jiān)聽同個(gè)變量,根據(jù)變量的值變化來執(zhí)行對(duì)應(yīng)的任務(wù),此處volatile的作用就是讓其它線程能即時(shí)感知變量值的改變

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
public class volatileTest {
 //定義一個(gè)共享變量,注意,必須用volatile修飾
 static volatile boolean flag = false;
 //定義個(gè)year,用來記錄某明星練習(xí)打籃球的年數(shù)
 private static double year;
 
 public static void main(String[] args) {
  //線程A,練習(xí)唱跳rap
  Thread threadA = new Thread(() -> {
   while (true) {
    if (!flag) {
     for (year = 0.5; year <= 5; year += 0.5) {
      System.out.println("蔡徐雞開始練習(xí)唱跳rap:已練習(xí)" + year + "年");
      try {
       Thread.sleep(288);
      } catch (InterruptedException e) {
       e.printStackTrace();
      }
      //眾所周知,練習(xí)兩年半即可出道
      if (year == 2.5) {
       System.out.println("===========================>成功練習(xí)兩年半,出道!!!");
       year = 0.5;
       flag = true;
       break;
      }
     }
    }
   }
  });
  //線程B,練習(xí)打籃球
  Thread threadB = new Thread(() -> {
   while (true) {
    if (flag) {
     System.out.println("蔡徐老母雞開始練習(xí)打籃球");
     break;
    }
   }
  });
  // 啟動(dòng)線程
  threadA.start();
  threadB.start();
 }
}

運(yùn)行結(jié)果:

蔡徐雞開始練習(xí)唱跳rap:已練習(xí)0.5年
蔡徐雞開始練習(xí)唱跳rap:已練習(xí)1.0年
蔡徐雞開始練習(xí)唱跳rap:已練習(xí)1.5年
蔡徐雞開始練習(xí)唱跳rap:已練習(xí)2.0年
蔡徐雞開始練習(xí)唱跳rap:已練習(xí)2.5年
===========================>成功練習(xí)兩年半,出道!!!
蔡徐老母雞開始練習(xí)打籃球

基于CountDownLatch

CountDownLatch是JUC包下的一個(gè)并發(fā)編程工具,主要有兩個(gè)方法,countDown和await,CountDownLatch底層維護(hù)了一個(gè)計(jì)數(shù)器,在實(shí)例化的時(shí)候設(shè)置,當(dāng)調(diào)用countDown方法時(shí),計(jì)數(shù)器減一,如果計(jì)數(shù)器在減一前已經(jīng)為0,那么什么都不會(huì)發(fā)生,如果減一后變成0,則喚醒所有等待的線程;await方法會(huì)使當(dāng)前線程等待,直到計(jì)數(shù)器為0

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
public class CountDownLatchTest {
 //定義個(gè)year,用來記錄某明星練習(xí)打籃球的年數(shù)
 private static double year;
 
 public static void main(String[] args) {
  CountDownLatch latch = new CountDownLatch(1);
  //線程A,練習(xí)唱跳rap
  Thread threadA = new Thread(() -> {
   for (year = 0.5; year <= 5; year += 0.5) {
    System.out.println("蔡徐雞開始練習(xí)唱跳rap:已練習(xí)" + year + "年");
    try {
     Thread.sleep(288);
    } catch (InterruptedException e) {
     e.printStackTrace();
    }
    //眾所周知,練習(xí)兩年半即可出道
    if (year == 2.5) {
     System.out.println("===========================>成功練習(xí)兩年半,出道!!!");
     //計(jì)數(shù)器減一
     latch.countDown();
    }
   }
  });
  //線程B,練習(xí)打籃球
  Thread threadB = new Thread(() -> {
   while (true) {
    try {
     //讓線程等待,如果計(jì)數(shù)器為0的話,則立即執(zhí)行
     latch.await();
    } catch (InterruptedException e) {
     e.printStackTrace();
    }
    System.out.println("蔡徐老母雞開始練習(xí)打籃球");
    break;
   }
  });
  // 啟動(dòng)線程
  threadA.start();
  threadB.start();
 }
}

運(yùn)行結(jié)果:

蔡徐雞開始練習(xí)唱跳rap:已練習(xí)0.5年
蔡徐雞開始練習(xí)唱跳rap:已練習(xí)1.0年
蔡徐雞開始練習(xí)唱跳rap:已練習(xí)1.5年
蔡徐雞開始練習(xí)唱跳rap:已練習(xí)2.0年
蔡徐雞開始練習(xí)唱跳rap:已練習(xí)2.5年
===========================>成功練習(xí)兩年半,出道!!!
蔡徐雞開始練習(xí)唱跳rap:已練習(xí)3.0年
蔡徐老母雞開始練習(xí)打籃球
蔡徐雞開始練習(xí)唱跳rap:已練習(xí)3.5年
蔡徐雞開始練習(xí)唱跳rap:已練習(xí)4.0年
蔡徐雞開始練習(xí)唱跳rap:已練習(xí)4.5年
蔡徐雞開始練習(xí)唱跳rap:已練習(xí)5.0年

如果你多運(yùn)行幾次,你會(huì)發(fā)現(xiàn)線程B執(zhí)行的時(shí)機(jī)是隨機(jī)的,但永遠(yuǎn)在計(jì)數(shù)器為0后才開始執(zhí)行,也就是說計(jì)數(shù)器為0后,線程A和線程B誰搶到鎖就誰執(zhí)行

文中所有demo都是復(fù)制即可運(yùn)行,大家還是要多動(dòng)手,家里有條件的都用idea跑一跑,沒條件的可以用手抄

總結(jié)

到此這篇關(guān)于java線程間通訊的文章就介紹到這了,更多相關(guān)java線程間通訊內(nèi)容請(qǐng)搜索服務(wù)器之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持服務(wù)器之家!

原文鏈接:https://blog.csdn.net/qq_33709582/article/details/113654386

延伸 · 閱讀

精彩推薦
主站蜘蛛池模板: 欧美18-19sex性处视频 | ass亚洲熟妇毛茸茸pics | 女人国产香蕉久久精品 | 好大好深好涨好烫还要 | 深夜在线观看网站 | 亚洲一级片在线播放 | 欧美一级在线播放 | 丁香五香天堂 | 99热久久这里只有精品6国产网 | 午夜一级毛片看看 | 吉泽明步高清无码中文 | 欧美人xxxxxbbbb | 午夜精品亚洲 | 太大了轻点阿受不了小说h 四色6677最新永久网站 | 91精品综合久久久久久五月天 | 精品国产剧情在线观看 | 亚洲欧美色综合图小说 | 国产一区日韩二区欧美三 | 出轨同学会2在线观看 | 青青成人在线 | 精品一区二区三区自拍图片区 | 东北美女野外bbwbbw免费 | 免费观看无人区完整版 | 精品久久久久久国产 | 国产成人精品曰本亚洲78 | 韩国三级在线 | 欧美日韩中文字幕一区二区高清 | 成人免费视频一区二区 | 免费看一级大片 | 亚洲+欧美+国产+综合 | 国产欧美久久一区二区 | 日韩基地1024首页 | 色交视频 | 果冻传媒天美传媒乌鸦传媒 | 国产精品日韩欧美一区二区三区 | 国产99视频精品免视看9 | 扒开腚眼子视频大全 | 国产一区二区视频在线播放 | 色综合视频在线 | 日韩精品一区二区三区中文在线 | 色综合中文字幕天天在线 |