欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Java等待喚醒機(jī)制線程通信原理解析

 更新時(shí)間:2019年12月18日 09:50:31   作者:我的腳印  
這篇文章主要介紹了Java等待喚醒機(jī)制線程通信原理解析,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下

這篇文章主要介紹了Java等待喚醒機(jī)制線程通信原理解析,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下

線程間通信

概念:多個(gè)線程在處理同一個(gè)資源,但是處理的動(dòng)作(線程的任務(wù))卻不相同。比如:線程A用來生成包子的,線程B用來吃包子的,包子可以理解為同一資源,線程A與線程B處理的動(dòng)作,一個(gè)是生產(chǎn),一個(gè)是消費(fèi),那么線程A與線程B之間就存在線程通信問題。

為什么要處理線程間通信:

多個(gè)線程并發(fā)執(zhí)行時(shí), 在默認(rèn)情況下CPU是隨機(jī)切換線程的,當(dāng)我們需要多個(gè)線程來共同完成一件任務(wù),并且我們希望他們有規(guī)律的執(zhí)行, 那么多線程之間需要一些協(xié)調(diào)通信,以此來幫我們達(dá)到多線程共同操作一份數(shù)據(jù)。

如何保證線程間通信有效利用資源:

多個(gè)線程在處理同一個(gè)資源,并且任務(wù)不同時(shí),需要線程通信來幫助解決線程之間對同一個(gè)變量的使用或操作。 就是多個(gè)線程在操作同一份數(shù)據(jù)時(shí), 避免對同一共享變量的爭奪。也就是我們需要通過一定的手段使各個(gè)線程能有效的利用資源。而這種手段即—— 等待喚醒機(jī)制。

等待喚醒機(jī)制

什么是等待喚醒機(jī)制

這是多個(gè)線程間的一種協(xié)作機(jī)制。談到線程我們經(jīng)常想到的是線程間的競爭(race),比如去爭奪鎖,但這并不是故事的全部,線程間也會(huì)有協(xié)作機(jī)制。就好比在公司里你和你的同事們,你們可能存在在晉升時(shí)的競爭,但更多時(shí)候你們更多是一起合作以完成某些任務(wù)。就是在一個(gè)線程進(jìn)行了規(guī)定操作后,就進(jìn)入等待狀態(tài)(wait()), 等待其他線程執(zhí)行完他們的指定代碼過后 再將其喚醒(notify());在有多個(gè)線程進(jìn)行等待時(shí), 如果需要,可以使用 notifyAll()來喚醒所有的等待線程。wait/notify 就是線程間的一種協(xié)作機(jī)制。

等待喚醒中的方法

等待喚醒機(jī)制就是用于解決線程間通信的問題的,使用到的3個(gè)方法的含義如下:

  • wait:線程不再活動(dòng),不再參與調(diào)度,進(jìn)入 wait set 中,因此不會(huì)浪費(fèi) CPU 資源,也不會(huì)去競爭鎖了,這時(shí)的線程狀態(tài)即是 WAITING。它還要等著別的線程執(zhí)行一個(gè)特別的動(dòng)作,也即是“通知(notify)”在這個(gè)對象上等待的線程從wait set 中釋放出來,重新進(jìn)入到調(diào)度隊(duì)列(ready queue)中
  • notify:則選取所通知對象的 wait set 中的一個(gè)線程釋放;例如,餐館有空位置后,等候就餐最久的顧客最先入座。
  • notifyAll:則釋放所通知對象的 wait set 上的全部線程。

注意:

哪怕只通知了一個(gè)等待的線程,被通知線程也不能立即恢復(fù)執(zhí)行,因?yàn)樗?dāng)初中斷的地方是在同步塊內(nèi),而此刻它已經(jīng)不持有鎖,所以她需要再次嘗試去獲取鎖(很可能面臨其它線程的競爭),成功后才能在當(dāng)初調(diào)用 wait 方法之后的地方恢復(fù)執(zhí)行。

總結(jié)如下:

如果能獲取鎖,線程就從 WAITING 狀態(tài)變成 RUNNABLE 狀態(tài);否則,從 wait set 出來,又進(jìn)入 entry set,線程就從 WAITING 狀態(tài)又變成 BLOCKED 狀態(tài)調(diào)用wait和notify方法需要注意的細(xì)節(jié)

  • wait方法與notify方法必須要由同一個(gè)鎖對象調(diào)用。因?yàn)椋簩?yīng)的鎖對象可以通過notify喚醒使用同一個(gè)鎖對象調(diào)用的wait方法后的線程。
  • wait方法與notify方法是屬于Object類的方法的。因?yàn)椋烘i對象可以是任意對象,而任意對象的所屬類都是繼承了Object類的。
  • wait方法與notify方法必須要在同步代碼塊或者是同步函數(shù)中使用。因?yàn)椋罕仨氁ㄟ^鎖對象調(diào)用這2個(gè)方法。

生產(chǎn)者與消費(fèi)者問題

等待喚醒機(jī)制其實(shí)就是經(jīng)典的“生產(chǎn)者與消費(fèi)者”的問題。就拿生產(chǎn)包子消費(fèi)包子來說等待喚醒機(jī)制如何有效利用資源:

/*
包子鋪線程生產(chǎn)包子,吃貨線程消費(fèi)包子。當(dāng)包子沒有時(shí)(包子狀態(tài)為false),吃貨線程等待,包子鋪線程生產(chǎn)包子
(即包子狀態(tài)為true),并通知吃貨線程(解除吃貨的等待狀態(tài)),因?yàn)橐呀?jīng)有包子了,那么包子鋪線程進(jìn)入等待狀態(tài)。
接下來,吃貨線程能否進(jìn)一步執(zhí)行則取決于鎖的獲取情況。如果吃貨獲取到鎖,那么就執(zhí)行吃包子動(dòng)作,包子吃完(包
子狀態(tài)為false),并通知包子鋪線程(解除包子鋪的等待狀態(tài)),吃貨線程進(jìn)入等待。包子鋪線程能否進(jìn)一步執(zhí)行則取
決于鎖的獲取情況

*/

代碼實(shí)現(xiàn)

包子類

package demo01;

public class BaoZi {
  String pier;
  String xianer;
  boolean flag = false;//包子資源 是否存在 包子資源狀態(tài)
}

吃貨線程類:

package demo01;

public class ChiHuo extends Thread {
  private BaoZi bz;

  public ChiHuo(String name, BaoZi bz) {
    super(name);
    this.bz = bz;
  }

  @Override
  public void run() {
    while (true) {
      synchronized (bz) {
        if (bz.flag == false) {//沒包子
          try {
            bz.wait();
          } catch (InterruptedException e) {
            e.printStackTrace();
          }
        }
        System.out.println("吃貨正在吃" + bz.pier + bz.xianer + "包子");
        bz.flag = false;
        bz.notify();
      }
    }
  }
}

包子鋪線程類:

package demo01;

public class BaoZiPu extends Thread {
  private BaoZi bz;

  public BaoZiPu(String name, BaoZi bz) {
    super(name);
    this.bz = bz;
  }

  @Override
  public void run() {
    int count = 0;
    //造包子
    while (true) {
      //同步
      synchronized (bz) {
        if (bz.flag == true) {//包子資源 存在
          try {
            bz.wait();
          } catch (InterruptedException e) {
            e.printStackTrace();
          }
        }
        // 沒有包子 造包子
        System.out.println("包子鋪開始做包子");
        if (count % 2 == 0) {
          // 冰皮 五仁
          bz.pier = "冰皮";
          bz.xianer = "五仁";
        } else {
          // 薄皮 牛肉大蔥
          bz.pier = "薄皮";
          bz.xianer = "牛肉大蔥";
        }
        count++;
        bz.flag = true;
        System.out.println("包子造好了:" + bz.pier + bz.xianer);
        System.out.println("吃貨來吃吧");
        //喚醒等待線程 (吃貨)
        bz.notify();
      }
    }
  }
}

測試類:

package demo01;

public class Demo {
  public static void main(String[] args) {
    //等待喚醒案例
    BaoZi bz = new BaoZi();
    ChiHuo ch = new ChiHuo("吃貨",bz);
    BaoZiPu bzp = new BaoZiPu("包子鋪",bz);
    ch.start();
    bzp.start();
  }
}

以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。

相關(guān)文章

  • JavaWeb?Servlet技術(shù)及其應(yīng)用實(shí)踐

    JavaWeb?Servlet技術(shù)及其應(yīng)用實(shí)踐

    這篇文章主要介紹了JavaWeb?Servlet技術(shù),Servlet指在服務(wù)器端執(zhí)行的一段Java代碼,可以接收用戶的請求和返回給用戶響應(yīng)結(jié)果,感興趣想要詳細(xì)了解可以參考下文
    2023-05-05
  • 關(guān)于dubbo的超時(shí)處理及重試原則

    關(guān)于dubbo的超時(shí)處理及重試原則

    這篇文章主要介紹了關(guān)于dubbo的超時(shí)處理及重試原則,具有很好的參考價(jià)值,希望對大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2023-08-08
  • Java數(shù)據(jù)結(jié)構(gòu)之順序表篇

    Java數(shù)據(jù)結(jié)構(gòu)之順序表篇

    順序表,全名順序存儲(chǔ)結(jié)構(gòu),是線性表的一種。線性表用于存儲(chǔ)邏輯關(guān)系為“一對一”的數(shù)據(jù),順序表自然也不例外,不僅如此,順序表對數(shù)據(jù)物理存儲(chǔ)結(jié)構(gòu)也有要求。順序表存儲(chǔ)數(shù)據(jù)時(shí),會(huì)提前申請一整塊足夠大小的物理空間,然后將數(shù)據(jù)依次存儲(chǔ)起來,存儲(chǔ)時(shí)數(shù)據(jù)元素間不留縫隙
    2022-01-01
  • SpringCloud中的服務(wù)接口(api)

    SpringCloud中的服務(wù)接口(api)

    這篇文章主要介紹了SpringCloud中的服務(wù)接口(api),具有很好的參考價(jià)值,希望對大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2024-04-04
  • python 與HFSS聯(lián)合仿真的教程講解

    python 與HFSS聯(lián)合仿真的教程講解

    這篇文章主要介紹了python 與HFSS聯(lián)合仿真的教程講解,具有很好的參考價(jià)值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2021-03-03
  • Spring?Data?JPA框架的Repository自定義實(shí)現(xiàn)詳解

    Spring?Data?JPA框架的Repository自定義實(shí)現(xiàn)詳解

    Spring?Data?JPA是Spring基于JPA規(guī)范的基礎(chǔ)上封裝的?套?JPA?應(yīng)?框架,可使開發(fā)者?極簡的代碼即可實(shí)現(xiàn)對數(shù)據(jù)庫的訪問和操作,本篇我們來了解Spring?Data?JPA框架的Repository自定義實(shí)現(xiàn)
    2022-04-04
  • Java?導(dǎo)出Excel增加下拉框選項(xiàng)

    Java?導(dǎo)出Excel增加下拉框選項(xiàng)

    這篇文章主要介紹了Java?導(dǎo)出Excel增加下拉框選項(xiàng),excel對于下拉框較多選項(xiàng)的,需要使用隱藏工作簿來解決,使用函數(shù)取值來做選項(xiàng),下文具體的操作詳情,需要的小伙伴可以參考一下
    2022-04-04
  • SpringBoot動(dòng)態(tài)Feign服務(wù)調(diào)用詳解

    SpringBoot動(dòng)態(tài)Feign服務(wù)調(diào)用詳解

    Feign是Netflix公司開發(fā)的一個(gè)聲明式的REST調(diào)用客戶端; Ribbon負(fù)載均衡、 Hystrⅸ服務(wù)熔斷是我們Spring Cloud中進(jìn)行微服務(wù)開發(fā)非常基礎(chǔ)的組件,在使用的過程中我們也發(fā)現(xiàn)它們一般都是同時(shí)出現(xiàn)的,而且配置也都非常相似
    2022-12-12
  • 帶你入門Java的方法

    帶你入門Java的方法

    這篇文章主要介紹了java基礎(chǔ)之方法詳解,文中有非常詳細(xì)的代碼示例,對正在學(xué)習(xí)java基礎(chǔ)的小伙伴們有非常好的幫助,需要的朋友可以參考下
    2021-07-07
  • idea離線使用jrebel的超詳細(xì)教程

    idea離線使用jrebel的超詳細(xì)教程

    IDEA上原生是不支持熱部署的,一般更新了 Java 文件后要手動(dòng)重啟 Tomcat 服務(wù)器,才能生效,下面通過本文給大家分享idea離線使用jrebel的超詳細(xì)教程(親測有效),感興趣的朋友一起看看吧
    2020-12-12

最新評論