<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          Java多線程學(xué)習(xí)之wait、notify/notifyAll 詳解

          共 3005字,需瀏覽 7分鐘

           ·

          2022-03-02 05:46


          1、wait()、notify/notifyAll() 方法是Object的本地final方法,無(wú)法被重寫(xiě)。

          2、wait()使當(dāng)前線程阻塞,前提是 必須先獲得鎖,一般配合synchronized 關(guān)鍵字使用,即,一般在synchronized 同步代碼塊里使用 wait()、notify/notifyAll() 方法。

          3、 由于 wait()、notify/notifyAll() 在synchronized 代碼塊執(zhí)行,說(shuō)明當(dāng)前線程一定是獲取了鎖的。

          當(dāng)線程執(zhí)行wait()方法時(shí)候,會(huì)釋放當(dāng)前的鎖,然后讓出CPU,進(jìn)入等待狀態(tài)。

          只有當(dāng) notify/notifyAll() 被執(zhí)行時(shí)候,才會(huì)喚醒一個(gè)或多個(gè)正處于等待狀態(tài)的線程,然后繼續(xù)往下執(zhí)行,直到執(zhí)行完synchronized 代碼塊的代碼或是中途遇到wait() ,再次釋放鎖。

          也就是說(shuō),notify/notifyAll() 的執(zhí)行只是喚醒沉睡的線程,而不會(huì)立即釋放鎖,鎖的釋放要看代碼塊的具體執(zhí)行情況。所以在編程中,盡量在使用了notify/notifyAll() 后立即退出臨界區(qū),以喚醒其他線程讓其獲得鎖。

          4、wait() 需要被try catch包圍,以便發(fā)生異常中斷也可以使wait等待的線程喚醒。

          5、notify 和wait 的順序不能錯(cuò),如果A線程先執(zhí)行notify方法,B線程在執(zhí)行wait方法,那么B線程是無(wú)法被喚醒的。

          6、notify 和 notifyAll的區(qū)別

          notify方法只喚醒一個(gè)等待(對(duì)象的)線程并使該線程開(kāi)始執(zhí)行。所以如果有多個(gè)線程等待一個(gè)對(duì)象,這個(gè)方法只會(huì)喚醒其中一個(gè)線程,選擇哪個(gè)線程取決于操作系統(tǒng)對(duì)多線程管理的實(shí)現(xiàn)。notifyAll 會(huì)喚醒所有等待(對(duì)象的)線程,盡管哪一個(gè)線程將會(huì)第一個(gè)處理取決于操作系統(tǒng)的實(shí)現(xiàn)。如果當(dāng)前情況下有多個(gè)線程需要被喚醒,推薦使用notifyAll 方法。比如在生產(chǎn)者-消費(fèi)者里面的使用,每次都需要喚醒所有的消費(fèi)者或是生產(chǎn)者,以判斷程序是否可以繼續(xù)往下執(zhí)行。


          7、在多線程中要測(cè)試某個(gè)條件的變化,使用if 還是while?


          要注意,notify喚醒沉睡的線程后,線程會(huì)接著上次的執(zhí)行繼續(xù)往下執(zhí)行。所以在進(jìn)行條件判斷時(shí)候,可以先把 wait 語(yǔ)句忽略不計(jì)來(lái)進(jìn)行考慮;顯然,要確保程序一定要執(zhí)行,并且要保證程序直到滿足一定的條件再執(zhí)行,要使用while進(jìn)行等待,直到滿足條件才繼續(xù)往下執(zhí)行。如下代碼:


          public?class?K?{
          ????//狀態(tài)鎖
          ????private?Object lock;
          ????//條件變量
          ????private?int?now,need;
          ????public?void?produce(int?num){
          ????????//同步
          ????????synchronized (lock){
          ???????????//當(dāng)前有的不滿足需要,進(jìn)行等待,直到滿足條件
          ????????????while(now < need){
          ????????????????try?{
          ????????????????????//等待阻塞
          ????????????????????lock.wait();
          ????????????????} catch?(InterruptedException e) {
          ????????????????????e.printStackTrace();
          ????????????????}
          ??????????????System.out.println("我被喚醒了!");
          ????????????}
          ???????????// 做其他的事情
          ????????}
          ????}
          }


          顯然,只有當(dāng)前值滿足需要值的時(shí)候,線程才可以往下執(zhí)行,所以,必須使用while 循環(huán)阻塞。注意,wait() 當(dāng)被喚醒時(shí)候,只是讓while循環(huán)繼續(xù)往下走.如果此處用if的話,意味著if繼續(xù)往下走,會(huì)跳出if語(yǔ)句塊。


          8、實(shí)現(xiàn)生產(chǎn)者和消費(fèi)者問(wèn)題?


          什么是生產(chǎn)者-消費(fèi)者問(wèn)題呢?



          如上圖,假設(shè)有一個(gè)公共的容量有限的池子,有兩種人,一種是生產(chǎn)者,另一種是消費(fèi)者。需要滿足如下條件:


          1、生產(chǎn)者產(chǎn)生資源往池子里添加,前提是池子沒(méi)有滿,如果池子滿了,則生產(chǎn)者暫停生產(chǎn),直到自己的生成能放下池子。


          2、消費(fèi)者消耗池子里的資源,前提是池子的資源不為空,否則消費(fèi)者暫停消耗,進(jìn)入等待直到池子里有資源數(shù)滿足自己的需求。


          - 倉(cāng)庫(kù)類


          /**
          ?* 生產(chǎn)者和消費(fèi)者的問(wèn)題
          ?* wait、notify/notifyAll() 實(shí)現(xiàn)
          ?*/

          public?class?Storage1?implements?AbstractStorage?{
          ????//倉(cāng)庫(kù)最大容量
          ????private?final int?MAX_SIZE = 100;
          ????//倉(cāng)庫(kù)存儲(chǔ)的載體
          ????private?LinkedList list?= new?LinkedList();

          ????//生產(chǎn)產(chǎn)品
          ????public?void?produce(int?num){
          ????????//同步
          ????????synchronized (list){
          ????????????//倉(cāng)庫(kù)剩余的容量不足以存放即將要生產(chǎn)的數(shù)量,暫停生產(chǎn)
          ????????????while(list.size()+num > MAX_SIZE){
          ????????????????System.out.println("【要生產(chǎn)的產(chǎn)品數(shù)量】:"?+ num + "\t【庫(kù)存量】:"
          ????????????????????????+ list.size() + "\t暫時(shí)不能執(zhí)行生產(chǎn)任務(wù)!");

          ????????????????try?{
          ????????????????????//條件不滿足,生產(chǎn)阻塞
          ????????????????????list.wait();
          ????????????????} catch?(InterruptedException e) {
          ????????????????????e.printStackTrace();
          ????????????????}
          ????????????}

          ????????????for(int?i=0;i????????????????list.add(new?Object());
          ????????????}

          ????????????System.out.println("【已經(jīng)生產(chǎn)產(chǎn)品數(shù)】:"?+ num + "\t【現(xiàn)倉(cāng)儲(chǔ)量為】:"?+ list.size());

          ????????????list.notifyAll();
          ????????}
          ????}

          ????//消費(fèi)產(chǎn)品
          ????public?void?consume(int?num){
          ????????synchronized (list){

          ????????????//不滿足消費(fèi)條件
          ????????????while(num > list.size()){
          ????????????????System.out.println("【要消費(fèi)的產(chǎn)品數(shù)量】:"?+ num + "\t【庫(kù)存量】:"
          ????????????????????????+ list.size() + "\t暫時(shí)不能執(zhí)行生產(chǎn)任務(wù)!");

          ????????????????try?{
          ????????????????????list.wait();
          ????????????????} catch?(InterruptedException e) {
          ????????????????????e.printStackTrace();
          ????????????????}
          ????????????}

          ????????????//消費(fèi)條件滿足,開(kāi)始消費(fèi)
          ????????????for(int?i=0;i????????????????list.remove();
          ????????????}

          ????????????System.out.println("【已經(jīng)消費(fèi)產(chǎn)品數(shù)】:"?+ num + "\t【現(xiàn)倉(cāng)儲(chǔ)量為】:"?+ list.size());

          ????????????list.notifyAll();
          ????????}
          ????}
          }


          - 抽象倉(cāng)庫(kù)類


          public?interface?AbstractStorage?{
          ????void?consume(int?num);
          ????void?produce(int?num);
          }


          - 生產(chǎn)者


          public?class?Producer?extends?Thread{
          ????//每次生產(chǎn)的數(shù)量
          ????private?int?num ;

          ????//所屬的倉(cāng)庫(kù)
          ????public?AbstractStorage abstractStorage;

          ????public?Producer(AbstractStorage abstractStorage){
          ????????this.abstractStorage = abstractStorage;
          ????}

          ????public?void?setNum(int?num){
          ????????this.num = num;
          ????}

          ????// 線程run函數(shù)
          ????@Override
          ????public?void?run()
          ????
          {
          ????????produce(num);
          ????}

          ????// 調(diào)用倉(cāng)庫(kù)Storage的生產(chǎn)函數(shù)
          ????public?void?produce(int?num)
          ????
          {
          ????????abstractStorage.produce(num);
          ????}
          }


          - 消費(fèi)者


          public?class?Consumer?extends?Thread{
          ????// 每次消費(fèi)的產(chǎn)品數(shù)量
          ????private?int?num;

          ????// 所在放置的倉(cāng)庫(kù)
          ????private?AbstractStorage abstractStorage1;

          ????// 構(gòu)造函數(shù),設(shè)置倉(cāng)庫(kù)
          ????public?Consumer(AbstractStorage abstractStorage1)
          ????
          {
          ????????this.abstractStorage1 = abstractStorage1;
          ????}

          ????// 線程run函數(shù)
          ????public?void?run()
          ????
          {
          ????????consume(num);
          ????}

          ????// 調(diào)用倉(cāng)庫(kù)Storage的生產(chǎn)函數(shù)
          ????public?void?consume(int?num)
          ????
          {
          ????????abstractStorage1.consume(num);
          ????}

          ????public?void?setNum(int?num){
          ????????this.num = num;
          ????}
          }


          - 測(cè)試


          public?class?Test{
          ????public?static?void?main(String[] args)?{
          ????????// 倉(cāng)庫(kù)對(duì)象
          ????????AbstractStorage abstractStorage = new?Storage1();

          ????????// 生產(chǎn)者對(duì)象
          ????????Producer p1 = new?Producer(abstractStorage);
          ????????Producer p2 = new?Producer(abstractStorage);
          ????????Producer p3 = new?Producer(abstractStorage);
          ????????Producer p4 = new?Producer(abstractStorage);
          ????????Producer p5 = new?Producer(abstractStorage);
          ????????Producer p6 = new?Producer(abstractStorage);
          ????????Producer p7 = new?Producer(abstractStorage);

          ????????// 消費(fèi)者對(duì)象
          ????????Consumer c1 = new?Consumer(abstractStorage);
          ????????Consumer c2 = new?Consumer(abstractStorage);
          ????????Consumer c3 = new?Consumer(abstractStorage);

          ????????// 設(shè)置生產(chǎn)者產(chǎn)品生產(chǎn)數(shù)量
          ????????p1.setNum(10);
          ????????p2.setNum(10);
          ????????p3.setNum(10);
          ????????p4.setNum(10);
          ????????p5.setNum(10);
          ????????p6.setNum(10);
          ????????p7.setNum(80);

          ????????// 設(shè)置消費(fèi)者產(chǎn)品消費(fèi)數(shù)量
          ????????c1.setNum(50);
          ????????c2.setNum(20);
          ????????c3.setNum(30);

          ????????// 線程開(kāi)始執(zhí)行
          ????????c1.start();
          ????????c2.start();
          ????????c3.start();

          ????????p1.start();
          ????????p2.start();
          ????????p3.start();
          ????????p4.start();
          ????????p5.start();
          ????????p6.start();
          ????????p7.start();
          ????}
          }


          - 輸出


          【要消費(fèi)的產(chǎn)品數(shù)量】:50????【庫(kù)存量】:0????暫時(shí)不能執(zhí)行生產(chǎn)任務(wù)!
          【要消費(fèi)的產(chǎn)品數(shù)量】:20????【庫(kù)存量】:0????暫時(shí)不能執(zhí)行生產(chǎn)任務(wù)!
          【要消費(fèi)的產(chǎn)品數(shù)量】:30????【庫(kù)存量】:0????暫時(shí)不能執(zhí)行生產(chǎn)任務(wù)!
          【已經(jīng)生產(chǎn)產(chǎn)品數(shù)】:10????【現(xiàn)倉(cāng)儲(chǔ)量為】:10
          【要消費(fèi)的產(chǎn)品數(shù)量】:30????【庫(kù)存量】:10????暫時(shí)不能執(zhí)行生產(chǎn)任務(wù)!
          【要消費(fèi)的產(chǎn)品數(shù)量】:20????【庫(kù)存量】:10????暫時(shí)不能執(zhí)行生產(chǎn)任務(wù)!
          【要消費(fèi)的產(chǎn)品數(shù)量】:50????【庫(kù)存量】:10????暫時(shí)不能執(zhí)行生產(chǎn)任務(wù)!
          【已經(jīng)生產(chǎn)產(chǎn)品數(shù)】:10????【現(xiàn)倉(cāng)儲(chǔ)量為】:20
          【已經(jīng)生產(chǎn)產(chǎn)品數(shù)】:10????【現(xiàn)倉(cāng)儲(chǔ)量為】:30
          【要消費(fèi)的產(chǎn)品數(shù)量】:50????【庫(kù)存量】:30????暫時(shí)不能執(zhí)行生產(chǎn)任務(wù)!
          【已經(jīng)消費(fèi)產(chǎn)品數(shù)】:20????【現(xiàn)倉(cāng)儲(chǔ)量為】:10
          【要消費(fèi)的產(chǎn)品數(shù)量】:30????【庫(kù)存量】:10????暫時(shí)不能執(zhí)行生產(chǎn)任務(wù)!
          【已經(jīng)生產(chǎn)產(chǎn)品數(shù)】:10????【現(xiàn)倉(cāng)儲(chǔ)量為】:20
          【要消費(fèi)的產(chǎn)品數(shù)量】:50????【庫(kù)存量】:20????暫時(shí)不能執(zhí)行生產(chǎn)任務(wù)!
          【要消費(fèi)的產(chǎn)品數(shù)量】:30????【庫(kù)存量】:20????暫時(shí)不能執(zhí)行生產(chǎn)任務(wù)!
          【已經(jīng)生產(chǎn)產(chǎn)品數(shù)】:10????【現(xiàn)倉(cāng)儲(chǔ)量為】:30
          【已經(jīng)消費(fèi)產(chǎn)品數(shù)】:30????【現(xiàn)倉(cāng)儲(chǔ)量為】:0
          【要消費(fèi)的產(chǎn)品數(shù)量】:50????【庫(kù)存量】:0????暫時(shí)不能執(zhí)行生產(chǎn)任務(wù)!
          【已經(jīng)生產(chǎn)產(chǎn)品數(shù)】:10????【現(xiàn)倉(cāng)儲(chǔ)量為】:10
          【要消費(fèi)的產(chǎn)品數(shù)量】:50????【庫(kù)存量】:10????暫時(shí)不能執(zhí)行生產(chǎn)任務(wù)!
          【已經(jīng)生產(chǎn)產(chǎn)品數(shù)】:80????【現(xiàn)倉(cāng)儲(chǔ)量為】:90
          【已經(jīng)消費(fèi)產(chǎn)品數(shù)】:50????【現(xiàn)倉(cāng)儲(chǔ)量為】:40


          來(lái)源:cnblogs.com/moongeek/p/7631447.html

          瀏覽 42
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評(píng)論
          圖片
          表情
          推薦
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  青青草a国产v | 蜜桃Av久久精品人人槡 | a√在线观看8 | 国产免费一级特黄A片 | 香蕉一区二区三区四区 |