最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

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

 更新時間:2021年02月05日 10:57:20   作者:負(fù)債程序猿  
這篇文章主要介紹了java線程間通訊的一些方法,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧

前言

并發(fā)編程中,我們可能會遇到這樣一個場景

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

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

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

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

1、基于synchronized

2、基于reentrantLock

3、基于volatile

4、基于countDownLatch

我目前就知道這四種

1、synchronized+wait() 和 notify()

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

public class SynchronizedTest {

 //定義個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í)打籃球");
    }
   }
  });
  //注意,一定要先啟動B,不然會導(dǎo)致B永遠(yuǎn)拿不到鎖
  threadB.start();
  threadA.start();
 }

 public static void main(String[] args) {
  SynchronizedTest test = new SynchronizedTest();
  test.run();
 }
}

運行結(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í)打籃球

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

2、基于ReentrantLock

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

public class LockTest {
  //定義個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 {
      //讓線程等待,如果計數(shù)器為0的話,則立即執(zhí)行
      condition.await();
     } catch (InterruptedException e) {
      e.printStackTrace();
     }
     System.out.println("蔡徐老母雞開始練習(xí)打籃球");
     break;
    }
    //業(yè)務(wù)代碼執(zhí)行完后解鎖
    lock.unlock();
   });
   //注意,一定要先啟動B,不然會導(dǎo)致B永遠(yuǎn)拿不到鎖
   threadB.start();
   threadA.start();
  }
 }

運行結(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

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

public class volatileTest {
 //定義一個共享變量,注意,必須用volatile修飾
 static volatile boolean flag = false;
 //定義個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;
    }
   }
  });
  // 啟動線程
  threadA.start();
  threadB.start();
 }
}

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

public class CountDownLatchTest {
 //定義個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í)兩年半,出道?。。?);
     //計數(shù)器減一
     latch.countDown();
    }
   }
  });
  //線程B,練習(xí)打籃球
  Thread threadB = new Thread(() -> {
   while (true) {
    try {
     //讓線程等待,如果計數(shù)器為0的話,則立即執(zhí)行
     latch.await();
    } catch (InterruptedException e) {
     e.printStackTrace();
    }
    System.out.println("蔡徐老母雞開始練習(xí)打籃球");
    break;
   }
  });
  // 啟動線程
  threadA.start();
  threadB.start();
 }
}

運行結(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年

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

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

總結(jié)

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

相關(guān)文章

  • Java實現(xiàn)排球比賽計分系統(tǒng)

    Java實現(xiàn)排球比賽計分系統(tǒng)

    這篇文章主要為大家詳細(xì)介紹了Java實現(xiàn)排球比賽計分系統(tǒng),具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2017-06-06
  • 詳解用maven將dubbo工程打成jar包運行

    詳解用maven將dubbo工程打成jar包運行

    這篇文章主要介紹了詳解用maven將dubbo工程打成jar包運行,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2019-04-04
  • java對接支付寶支付接口簡單步驟記錄

    java對接支付寶支付接口簡單步驟記錄

    最近項目APP需要接入微信、支付寶支付功能,在分配開發(fā)任務(wù)時,聽說微信支付接口比支付寶支付接口要難實現(xiàn),這篇文章主要給大家介紹了關(guān)于java對接支付寶支付接口的簡單步驟,需要的朋友可以參考下
    2024-05-05
  • Springboot中的@Conditional注解詳解

    Springboot中的@Conditional注解詳解

    這篇文章主要介紹了Springboot中的@Conditional注解詳解,@Conditional來源于spring-context包下的一個注解,Conditional中文是條件的意思,@Conditional注解它的作用是按照一定的條件進(jìn)行判斷,滿足條件給容器注冊bean,需要的朋友可以參考下
    2023-09-09
  • Struts2源碼分析之ParametersInterceptor攔截器

    Struts2源碼分析之ParametersInterceptor攔截器

    這篇文章主要介紹了Struts2源碼分析之ParametersInterceptor攔截器,ParametersInterceptor攔截器其主要功能是把ActionContext中的請求參數(shù)設(shè)置到ValueStack中,,需要的朋友可以參考下
    2019-06-06
  • 詳解Spring如何掃描自定義的注解

    詳解Spring如何掃描自定義的注解

    本文給大家詳細(xì)介紹了Spring如何掃描自定義的注解,在Spring中,可以使用注解來實現(xiàn)依賴注入、AOP等功能,同時,Spring也支持自定義注解,使得開發(fā)人員可以更靈活地使用注解,需要的朋友可以參考下
    2024-02-02
  • Java如何實現(xiàn)List自定義排序

    Java如何實現(xiàn)List自定義排序

    這篇文章主要介紹了Java如何實現(xiàn)List自定義排序,幫助大家更好的理解和使用Java,感興趣的朋友可以了解下
    2020-09-09
  • java WSDL接口webService實現(xiàn)方式

    java WSDL接口webService實現(xiàn)方式

    這篇文章主要為大家詳細(xì)介紹了java WSDL接口webService實現(xiàn)方式的相關(guān)資料,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2017-04-04
  • 簡單了解Java關(guān)鍵字throw和throws的區(qū)別

    簡單了解Java關(guān)鍵字throw和throws的區(qū)別

    這篇文章主要介紹了簡單了解Java關(guān)鍵字throw和throws的區(qū)別,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下
    2019-11-11
  • 如何使用JJWT及JWT講解和工具類

    如何使用JJWT及JWT講解和工具類

    關(guān)于JWT的文章網(wǎng)上已經(jīng)多如牛毛了,但是相信很多同學(xué)學(xué)的還是云里霧里,所以在我學(xué)習(xí)JWT之后盡量用最簡潔的描述寫下這篇文章用于日后復(fù)習(xí),與此同時也希望可以幫助同學(xué)們共同進(jìn)步
    2021-09-09

最新評論

武冈市| 江津市| 永城市| 隆化县| 云龙县| 亚东县| 富顺县| 金溪县| 垦利县| 兴和县| 德保县| 延川县| 汝南县| 阿瓦提县| 潼关县| 北碚区| 镇康县| 库尔勒市| 杭州市| 武冈市| 临沂市| 潍坊市| 乌兰察布市| 莱西市| 会理县| 武邑县| 饶河县| 庆云县| 新乐市| 太湖县| 启东市| 勃利县| 美姑县| 双牌县| 南木林县| 乾安县| 麟游县| 正镶白旗| 浦东新区| 五寨县| 梧州市|