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

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

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

服務器之家 - 編程語言 - Java教程 - Java中線程的等待與喚醒_動力節(jié)點Java學院整理

Java中線程的等待與喚醒_動力節(jié)點Java學院整理

2020-10-30 23:34動力節(jié)點 Java教程

在Object.java中,定義了wait(), notify()和notifyAll()等接口。wait()的作用是讓當前線程進入等待狀態(tài),同時,wait()也會讓當前線程釋放它所持有的鎖。下面通過本文給大家介紹Java中線程的等待與喚醒知識,感興趣的朋友一起看看吧

wait(), notify(), notifyAll()等方法介紹

在Object.java中,定義了wait(), notify()和notifyAll()等接口。wait()的作用是讓當前線程進入等待狀態(tài),同時,wait()也會讓當前線程釋放它所持有的鎖。而notify()和notifyAll()的作用,則是喚醒當前對象上的等待線程;notify()是喚醒單個線程,而notifyAll()是喚醒所有的線程。

Object類中關于等待/喚醒的API詳細信息如下:

notify()        -- 喚醒在此對象監(jiān)視器上等待的單個線程。
notifyAll()   -- 喚醒在此對象監(jiān)視器上等待的所有線程。
wait()                                         -- 讓當前線程處于“等待(阻塞)狀態(tài)”,“直到其他線程調(diào)用此對象的 notify() 方法或 notifyAll() 方法”,當前線程被喚醒(進入“就緒狀態(tài)”)。
wait(long timeout)                    -- 讓當前線程處于“等待(阻塞)狀態(tài)”,“直到其他線程調(diào)用此對象的 notify() 方法或 notifyAll() 方法,或者超過指定的時間量”,當前線程被喚醒(進入“就緒狀態(tài)”)。
wait(long timeout, int nanos)  -- 讓當前線程處于“等待(阻塞)狀態(tài)”,“直到其他線程調(diào)用此對象的 notify() 方法或 notifyAll() 方法,或者其他某個線程中斷當前線程,或者已超過某個實際時間量”,當前線程被喚醒(進入“就緒狀態(tài)”)。 

 wait()和notify()示例

下面通過示例演示"wait()和notify()配合使用的情形"。

?
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
// WaitTest.java的源碼
class ThreadA extends Thread{
  public ThreadA(String name) {
    super(name);
  }
  public void run() {
    synchronized (this) {
      System.out.println(Thread.currentThread().getName()+" call notify()");
      // 喚醒當前的wait線程
      notify();
    }
  }
}
public class WaitTest {
  public static void main(String[] args) {
    ThreadA t1 = new ThreadA("t1");
    synchronized(t1) {
      try {
        // 啟動“線程t1”
        System.out.println(Thread.currentThread().getName()+" start t1");
        t1.start();
        // 主線程等待t1通過notify()喚醒。
        System.out.println(Thread.currentThread().getName()+" wait()");
        t1.wait();
        System.out.println(Thread.currentThread().getName()+" continue");
      } catch (InterruptedException e) {
        e.printStackTrace();
      }
    }
  }
}

運行結(jié)果:

?
1
2
3
4
main start t1
main wait()
t1 call notify()
main continue

結(jié)果說明:

如下圖,說明了“主線程”和“線程t1”的流程。

(01) 注意,圖中"主線程" 代表“主線程main”。"線程t1" 代表WaitTest中啟動的“線程t1”。 而“鎖” 代表“t1這個對象的同步鎖”。

(02) “主線程”通過 new ThreadA("t1") 新建“線程t1”。隨后通過synchronized(t1)獲取“t1對象的同步鎖”。然后調(diào)用t1.start()啟動“線程t1”。

(03) “主線程”執(zhí)行t1.wait() 釋放“t1對象的鎖”并且進入“等待(阻塞)狀態(tài)”。等待t1對象上的線程通過notify() 或 notifyAll()將其喚醒。

(04) “線程t1”運行之后,通過synchronized(this)獲取“當前對象的鎖”;接著調(diào)用notify()喚醒“當前對象上的等待線程”,也就是喚醒“主線程”。

(05) “線程t1”運行完畢之后,釋放“當前對象的鎖”。緊接著,“主線程”獲取“t1對象的鎖”,然后接著運行。

Java中線程的等待與喚醒_動力節(jié)點Java學院整理

對于上面的代碼?曾經(jīng)有個朋友問到過:t1.wait()應該是讓“線程t1”等待;但是,為什么卻是讓“主線程main”等待了呢

在解答該問題前,我們先看看jdk文檔中關于wait的一段介紹:

Causes the current thread to wait until another thread invokes the notify() method or the notifyAll() method for this object.
In other words, this method behaves exactly as if it simply performs the call wait(0).
The current thread must own this object's monitor. The thread releases ownership of this monitor and waits until another thread notifies threads waiting on this object's monitor to wake up either through a call to the notify method or the notifyAll method. The thread then waits until it can re-obtain ownership of the monitor and resumes execution.

注意:jdk的解釋中,說wait()的作用是讓“當前線程”等待,而“當前線程”是指正在cpu上運行的線程!

這也意味著,雖然t1.wait()是通過“線程t1”調(diào)用的wait()方法,但是調(diào)用t1.wait()的地方是在“主線程main”中。而主線程必須是“當前線程”,也就是運行狀態(tài),才可以執(zhí)行t1.wait()。所以,此時的“當前線程”是“主線程main”!因此,t1.wait()是讓“主線程”等待,而不是“線程t1”! 

wait(long timeout)和notify()

wait(long timeout)會讓當前線程處于“等待(阻塞)狀態(tài)”,“直到其他線程調(diào)用此對象的 notify() 方法或 notifyAll() 方法,或者超過指定的時間量”,當前線程被喚醒(進入“就緒狀態(tài)”)。

下面的示例就是演示wait(long timeout)在超時情況下,線程被喚醒的情況。  

?
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
// WaitTimeoutTest.java的源碼
class ThreadA extends Thread{
  public ThreadA(String name) {
    super(name);
  }
  public void run() {
    System.out.println(Thread.currentThread().getName() + " run ");
    // 死循環(huán),不斷運行。
    while(true)
      ;
  }
}
public class WaitTimeoutTest {
  public static void main(String[] args) {
    ThreadA t1 = new ThreadA("t1");
    synchronized(t1) {
      try {
        // 啟動“線程t1”
        System.out.println(Thread.currentThread().getName() + " start t1");
        t1.start();
        // 主線程等待t1通過notify()喚醒 或 notifyAll()喚醒,或超過3000ms延時;然后才被喚醒。
        System.out.println(Thread.currentThread().getName() + " call wait ");
        t1.wait(3000);
        System.out.println(Thread.currentThread().getName() + " continue");
      } catch (InterruptedException e) {
        e.printStackTrace();
      }
    }
  }
}

運行結(jié)果:

?
1
2
3
4
main start t1
main call wait
t1 run         // 大約3秒之后...輸出“main continue”
main continue

結(jié)果說明:

如下圖,說明了“主線程”和“線程t1”的流程。

(01) 注意,圖中"主線程" 代表WaitTimeoutTest主線程(即,線程main)。"線程t1" 代表WaitTest中啟動的線程t1。 而“鎖” 代表“t1這個對象的同步鎖”。

(02) 主線程main執(zhí)行t1.start()啟動“線程t1”。

(03) 主線程main執(zhí)行t1.wait(3000),此時,主線程進入“阻塞狀態(tài)”。需要“用于t1對象鎖的線程通過notify() 或者 notifyAll()將其喚醒” 或者 “超時3000ms之后”,主線程main才進入到“就緒狀態(tài)”,然后才可以運行。

(04) “線程t1”運行之后,進入了死循環(huán),一直不斷的運行。

(05) 超時3000ms之后,主線程main會進入到“就緒狀態(tài)”,然后接著進入“運行狀態(tài)”。 

Java中線程的等待與喚醒_動力節(jié)點Java學院整理

wait() 和 notifyAll()

通過前面的示例,我們知道 notify() 可以喚醒在此對象監(jiān)視器上等待的單個線程。

下面,我們通過示例演示notifyAll()的用法;它的作用是喚醒在此對象監(jiān)視器上等待的所有線程。 

?
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 NotifyAllTest {
   private static Object obj = new Object();
   public static void main(String[] args) {
     ThreadA t1 = new ThreadA("t1");
     ThreadA t2 = new ThreadA("t2");
     ThreadA t3 = new ThreadA("t3");
     t1.start();
     t2.start();
     t3.start();
     try {
       System.out.println(Thread.currentThread().getName()+" sleep(3000)");
       Thread.sleep(3000);
     } catch (InterruptedException e) {
       e.printStackTrace();
     }
     synchronized(obj) {
       // 主線程等待喚醒。
       System.out.println(Thread.currentThread().getName()+" notifyAll()");
       obj.notifyAll();
     }
   }
   static class ThreadA extends Thread{
     public ThreadA(String name){
       super(name);
     }
     public void run() {
       synchronized (obj) {
         try {
           // 打印輸出結(jié)果
           System.out.println(Thread.currentThread().getName() + " wait");
           // 喚醒當前的wait線程
           obj.wait();
           // 打印輸出結(jié)果
           System.out.println(Thread.currentThread().getName() + " continue");
         } catch (InterruptedException e) {
           e.printStackTrace();
         }
       }
     }
   }
 }

運行結(jié)果: 

?
1
2
3
4
5
6
7
8
t1 wait
main sleep(3000)
t3 wait
t2 wait
main notifyAll()
t2 continue
t3 continue
t1 continue

結(jié)果說明:

參考下面的流程圖。

(01) 主線程中新建并且啟動了3個線程"t1", "t2"和"t3"。

(02) 主線程通過sleep(3000)休眠3秒。在主線程休眠3秒的過程中,我們假設"t1", "t2"和"t3"這3個線程都運行了。以"t1"為例,當它運行的時候,它會執(zhí)行obj.wait()等待其它線程通過notify()或額nofityAll()來喚醒它;相同的道理,"t2"和"t3"也會等待其它線程通過nofity()或nofityAll()來喚醒它們。

(03) 主線程休眠3秒之后,接著運行。執(zhí)行 obj.notifyAll() 喚醒obj上的等待線程,即喚醒"t1", "t2"和"t3"這3個線程。 緊接著,主線程的synchronized(obj)運行完畢之后,主線程釋放“obj鎖”。這樣,"t1", "t2"和"t3"就可以獲取“obj鎖”而繼續(xù)運行了! 

Java中線程的等待與喚醒_動力節(jié)點Java學院整理

為什么notify(), wait()等函數(shù)定義在Object中,而不是Thread中

Object中的wait(), notify()等函數(shù),和synchronized一樣,會對“對象的同步鎖”進行操作。

wait()會使“當前線程”等待,因為線程進入等待狀態(tài),所以線程應該釋放它鎖持有的“同步鎖”,否則其它線程獲取不到該“同步鎖”而無法運行!

OK,線程調(diào)用wait()之后,會釋放它鎖持有的“同步鎖”;而且,根據(jù)前面的介紹,我們知道:等待線程可以被notify()或notifyAll()喚醒。現(xiàn)在,請思考一個問題:notify()是依據(jù)什么喚醒等待線程的?或者說,wait()等待線程和notify()之間是通過什么關聯(lián)起來的?答案是:依據(jù)“對象的同步鎖”。

負責喚醒等待線程的那個線程(我們稱為“喚醒線程”),它只有在獲取“該對象的同步鎖”(這里的同步鎖必須和等待線程的同步鎖是同一個),并且調(diào)用notify()或notifyAll()方法之后,才能喚醒等待線程。雖然,等待線程被喚醒;但是,它不能立刻執(zhí)行,因為喚醒線程還持有“該對象的同步鎖”。必須等到喚醒線程釋放了“對象的同步鎖”之后,等待線程才能獲取到“對象的同步鎖”進而繼續(xù)運行。

總之,notify(), wait()依賴于“同步鎖”,而“同步鎖”是對象鎖持有,并且每個對象有且僅有一個!這就是為什么notify(), wait()等函數(shù)定義在Object類,而不是Thread類中的原因。

以上所述是小編給大家介紹的Java中線程的等待與喚醒,希望對大家有所幫助,如果大家有任何疑問請給我留言,小編會及時回復大家的。在此也非常感謝大家對服務器之家網(wǎng)站的支持!

延伸 · 閱讀

精彩推薦
主站蜘蛛池模板: 欧美国产影院 | 国产aaaaa一级毛片 | 日剧整部剧护妻狂魔免费观看全集 | 国产精品原创巨作无遮挡 | 欧美老肥妇bbbw | 亚洲a视频在线 | 精品在线免费播放 | 海绵宝宝第二季全集免费观看 | 农村老妇1乱69系列小说 | 久热人人综合人人九九精品视频 | 欧美成人momandson | 狠狠色狠狠色综合曰曰 | 欧美一级二级片 | 日本人与黑人做爰视频网站 | 国产免费不卡视频 | 亚洲欧美日韩综合一区久久 | 精品国产欧美一区二区 | 亚洲色图欧美色 | 欧美日韩国产亚洲人成 | 爱操综合网 | 69av导航 | 亚洲系列国产系列 | 99精品久久精品一区二区小说 | 亚洲福利二区 | 国产一区二区免费福利片 | 五月天色综合 | zoomkool最新版 | 爱情岛永久成人免费网站 | 大陆日韩欧美 | 2019中文字幕在线视频 | 欧美一区二区三区综合色视频 | 韩国三级在线 | 亚洲日韩精品欧美一区二区一 | 赤坂丽女医bd无删减在线观看 | 欧美午夜寂寞影院安卓列表 | 黄+色+性+人免费 | 99视频久久精品久久 | 亚洲一区二区三区久久精品 | 男人天堂网www | 经典WC女厕所里TV | 国产亚洲自愉自愉 |