激情久久久_欧美视频区_成人av免费_不卡视频一二三区_欧美精品在欧美一区二区少妇_欧美一区二区三区的

服務器之家:專注于服務器技術及軟件下載分享
分類導航

PHP教程|ASP.NET教程|JAVA教程|ASP教程|

服務器之家 - 編程語言 - JAVA教程 - Java notify和notifyAll的區別和相同

Java notify和notifyAll的區別和相同

2020-06-15 12:02姚國俊 JAVA教程

本文主要介紹Java notify和notifyAll的知識,這里整理詳細的資料來說明notify 和NotifAll的區別,有需要的小伙伴可以參考下

經常在往上逛,關于在java中notify和notifyAll,經常有人有以下的說法:

notify只會通知一個在等待的對象,而notifyAll會通知所有在等待的對象,并且所有對象都會繼續運行

并且,好像都有例子可以證明。上面的說法,可以說對,也可以說不對。究其原因,在于其中有一點很關鍵,官方的說法如下所示:

wait,notify,notifyAll:

此方法只應由作為此對象監視器的所有者的線程來調用。通過以下三種方法之一,線程可以成為此對象監視器的所有者

通過執行此對象的同步實例方法。
通過執行在此對象上進行同步的 synchronized 語句的正文。
對于 Class 類型的對象,可以通過執行該類的同步靜態方法。 
 一次只能有一個線程擁有對象的監視器。

以上說法,摘自javadoc。意思即,在調用中,必須持有對象監視器(即鎖),我們可以理解為需要在synchronized方法內運行。那么由此話的隱含意思,即如果要繼續由同步塊包含的代碼塊,需要重新獲取鎖才可以。這句話,在javadoc中這樣描述:

wait

此方法導致當前線程(稱之為 T)將其自身放置在對象的等待集中,然后放棄此對象上的所有同步要求。出于線程調度
目的,在發生以下四種情況之一前,線程 T 被禁用,且處于休眠狀態:
其他某個線程調用此對象的 notify 方法,并且線程 T 碰巧被任選為被喚醒的線程。
其他某個線程調用此對象的 notifyAll 方法。
其他某個線程中斷線程 T。
大約已經到達指定的實際時間。但是,如果 timeout 為零,則不考慮實際時間,在獲得通知前該線程將一直等待。
 然后,從對象的等待集中刪除線程 T,并重新進行線程調度。然后,該線程以常規方式與其他線程競爭,以獲得在該對
象上同步的權利;一旦獲得對該對象的控制權,該對象上的所有其同步聲明都將被恢復到以前的狀態,這就是調用 wait
 方法時的情況。然后,線程 T 從 wait 方法的調用中返回。所以,從 wait 方法返回時,該對象和線程 T 的同步狀態與調
用 wait 方法時的情況完全相同。

即必須重新進行獲取鎖,這樣對于notifyAll來說,雖然所有的線程都被通知了。但是這些線程都會進行競爭,且只會有一個線程成功獲取到鎖,在這個線程沒有執行完畢之前,其他的線程就必須等待了(只是這里不需要再notifyAll通知了,因為已經notifyAll了,只差獲取鎖了)有如下一個代碼,可以重現這個現象。

首先,定義一個可以運行的線程類,如下所示:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
private static final Object obj = new Object();
  static class R implements Runnable {
    int i;
 
    R(int i) {
      this.i = i;
    }
 
    public void run() {
      try {
        synchronized(obj) {
          System.out.println("線程-> " + i + " 等待中");
          obj.wait();
          System.out.println("線程-> " + i + " 在運行了");
          Thread.sleep(30000);
        }
      } catch(Exception e) {
        e.printStackTrace();
      }
    }
  }

注意上面的run方法內部,我們在wait()之后,打印一句話,然后將當前代碼,暫停30秒。關于sleep方法,是這樣描述的:
該線程不丟失任何監視器的所屬權。
即仍然持有鎖。

然后,定義一個main方法來運行這些線程,如下所示:

?
1
2
3
4
5
6
7
8
9
10
11
12
Thread[] rs = new Thread[10];
    for(int i = 0;i < 10;i++) {
      rs[i] = new Thread(new R(i));
    }
    for(Thread r : rs) {
      r.start();
    }
 
    Thread.sleep(5000);
    synchronized(obj) {
      obj.notifyAll();
    }

我們定義了10個線程,然后全部運行之。因為有wait,10個線程都會在打印出 “開始運行”之后等待。然后main方法調用notifyAll。這里的輸出就會出現如下的輸出:

線程-> 0 等待中
線程->  4 等待中
線程->  5 等待中
線程->  3 等待中
線程->  2 等待中
線程->  1 等待中
線程->  6 等待中
線程->  7 等待中
線程->  8 等待中
線程->  9 等待中
線程->  9 在運行了
...30秒之內,不會有其他輸出

在上面的輸出中,在wait之后,只有一個線程輸出了”在運行了”語句,并且在一段時間內(這里為30秒),不會有其他輸出。即表示,在當前代碼持有鎖之間,其他線程是不會輸出的。

最后結論就是:被wait的線程,想要繼續運行的話,它必須滿足2個條件:

由其他線程notify或notifyAll了,并且當前線程被通知到了

經過和其他線程進行鎖競爭,成功獲取到鎖了2個條件,缺一不可。其實在實現層面,notify和notifyAll都達到相同的效果,會有一個線程繼續運行。但notifyAll免去了,線程運行完了通知其他線程的必要,因為已經通知過了。什么時候用notify,什么時候使用notifyAll,這就得看實際的情況了。

以上就是對Java notify和NotifyAll的資料整理,后續繼續補充相關資料謝謝大家對本站的支持!

延伸 · 閱讀

精彩推薦
主站蜘蛛池模板: 国产小视频一区 | 久啪视频 | 久久伊| 国产成人在线观看免费网站 | 手机在线看片国产 | 欧美激情第一区 | 欧美a视频 | 亚洲性夜色噜噜噜7777 | 91亚洲精品一区二区福利 | 色播av在线| 精品一二三区视频 | 国产精品99久久99久久久二 | 久久精品国产亚洲aa级女大片 | 1区2区3区国产 | 国产69精品久久久久99尤 | 国产免费视频一区二区裸体 | 澳门一级淫片免费视频 | 欧美黄色大片免费观看 | 亚洲成人入口 | 国产高清在线观看av | 日韩黄a| 999久久久国产999久久久 | 午夜激情视频免费 | 在线免费观看精品 | 中国av中文字幕 | 国产小视频在线 | www国产成人免费观看视频,深夜成人网 | 热re91久久精品国产99热 | 久久久国产精品免费观看 | 国产精品一区99 | 亚洲国产高清一区 | 精品国产一区二区久久 | 毛片在线免费观看视频 | 欧美黄色看 | 欧美精品免费一区二区三区 | 射逼网站 | 日韩精品羞羞答答 | 成人在线视频免费 | 精品一区二区三区欧美 | 羞羞视频免费网站含羞草 | 综合在线视频 |