国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

Java 多線程編程之:notify 和 wait 用法

eccozhou / 3325人閱讀

摘要:和簡介和均為的方法暫停一個線程喚醒一個線程從以上的定義中,我們可以了解到以下事實想要使用這兩個方法,我們需要先有一個對象。在中任何一個時刻,對象的控制權只能被一個線程擁有。若有多個線程處于此控制權下的狀態,只有一個會被喚醒。

最近看帖子,發現一道面試題:

啟動兩個線程, 一個輸出 1,3,5,7…99, 另一個輸出 2,4,6,8…100 最后 STDOUT 中按序輸出 1,2,3,4,5…100

題目要求用 Java 的 wait + notify 機制來實現,重點考察對于多線程可見性的理解。

wait 和 notify 簡介

wait 和 notify 均為 Object 的方法:

Object.wait() —— 暫停一個線程

Object.notify() —— 喚醒一個線程

從以上的定義中,我們可以了解到以下事實:

想要使用這兩個方法,我們需要先有一個對象 Object。

在多個線程之間,我們可以通過調用同一個對象wait()notify()來實現不同的線程間的可見。

對象控制權(monitor)

在使用 wait 和 notify 之前,我們需要先了解對象的控制權(monitor)。在 Java 中任何一個時刻,對象的控制權只能被一個線程擁有。如何理解控制權呢?請先看下面的簡單代碼:

public class ThreadTest {
    public static void main(String[] args) {
        Object object = new Object();
        new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    object.wait();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }).start();
    }
}

直接執行,我們將會得到以下異常:

Exception in thread "Thread-0" java.lang.IllegalMonitorStateException
    at java.lang.Object.wait(Native Method)
    at java.lang.Object.wait(Object.java:502)
    at com.xiangyu.demo.ThreadTest$1.run(ThreadTest.java:10)
    at java.lang.Thread.run(Thread.java:748)

出錯的代碼在:object.wait();。這里我們需要了解以下事實:

無論是執行對象的 wait、notify 還是 notifyAll 方法,必須保證當前運行的線程取得了該對象的控制權(monitor)

如果在沒有控制權的線程里執行對象的以上三種方法,就會報 java.lang.IllegalMonitorStateException 異常。

JVM 基于多線程,默認情況下不能保證運行時線程的時序性

在上面的示例代碼中,我們 new 了一個 Thread,但是對象 object 的控制權仍在主線程里。所以會報 java.lang.IllegalMonitorStateException 。

我們可以通過同步鎖來獲得對象控制權,例如:synchronized 代碼塊。對以上的示例代碼做改造:

public class ThreadTest {
    public static void main(String[] args) {
        Object object = new Object();
        new Thread(new Runnable() {
            @Override
            public void run() {
                synchronized (object){ // 修改處
                    try {
                        object.wait();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
        }).start();
    }
}

再次執行,代碼不再報錯。

我們可以得到以下結論:

調用對象的wait()notify()方法,需要先取得對象的控制權

可以使用synchronized (object)來取得對于 object 對象的控制權

解題

了解了對象控制權之后,我們就可以正常地使用 notify 和 wait 了,下面給出我的解題方法,供參考。

public class ThreadTest {
    private final Object flag = new Object();

    public static void main(String[] args) {
        ThreadTest threadTest = new ThreadTest();
        ThreadA threadA = threadTest.new ThreadA();
        threadA.start();
        ThreadB threadB = threadTest.new ThreadB();
        threadB.start();
    }

    class ThreadA extends Thread {
        @Override
        public void run() {
            synchronized (flag) {
                for (int i = 0; i <= 100; i += 2) {
                    flag.notify();
                    System.out.println(i);
                    try {
                        flag.wait();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }

        }
    }

    class ThreadB extends Thread {
        @Override
        public void run() {
            synchronized (flag) {
                for (int i = 1; i < 100; i += 2) {
                    flag.notify();
                    System.out.println(i);
                    try {
                        flag.wait();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
        }
    }
}
發散:notify()notifyAll()

這兩個方法均為 native 方法,在JDK 1.8 中的關于notify()的JavaDoc如下:

Wakes up a single thread that is waiting on this object"s monitor. If any threads are waiting on this object, one of them is chosen to be awakened.

譯為:

喚醒此 object 控制權下的一個處于 wait 狀態的線程。若有多個線程處于此 object 控制權下的 wait 狀態,只有一個會被喚醒。

也就是說,如果有多個線程在 wait 狀態,我們并不知道哪個線程會被喚醒。

在JDK 1.8 中的關于notifyAll()的JavaDoc如下:

Wakes up all threads that are waiting on this object"s monitor.

譯為:

喚醒所有處于此 object 控制權下的 wait 狀態的線程。

所以,我們需要根據實際的業務場景來考慮如何使用。

文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。

轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/77389.html

相關文章

  • java并發編程學習線程的生命周期-wait,notify,notifyall(六)

    摘要:不釋放持有的鎖,釋放鎖。在調用方法前,必須持有鎖,調用喚醒,也要持有鎖。休眠一定時間后,進入就緒狀態。這兩個都能被方法中斷當前狀態。用法方獲取鎖判斷條件,不滿足繼續滿足執行其他業務方獲取鎖改變條件通知為什么是而不是會一直循環,直到條件滿足。 sleep和wait sleep是Thread類的方法,wait是Object的方法。 sleep可以到處使用,wait必須是在同步方法或者代碼...

    Terry_Tai 評論0 收藏0
  • Java并發編程線程間通訊(上)wait/notify機制

    摘要:用線程表示維修的過程維修結束把廁所置為可用狀態維修工把廁所修好了,準備釋放鎖了這個維修計劃的內容就是當維修工進入廁所之后,先把門鎖上,然后開始維修,維修結束之后把的字段設置為,以表示廁所可用。 線程間通信 如果一個線程從頭到尾執行完也不和別的線程打交道的話,那就不會有各種安全性問題了。但是協作越來越成為社會發展的大勢,一個大任務拆成若干個小任務之后,各個小任務之間可能也需要相互協作最終...

    Lionad-Morotar 評論0 收藏0
  • Java并發編程線程間通訊(下)-生產者與消費者

    摘要:前文回顧上一篇文章重點嘮叨了中協調線程間通信的機制,它有力的保證了線程間通信的安全性以及便利性。所以同一時刻廚師線程和服務員線程不會同時在等待隊列中。對于在操作系統中線程的阻塞狀態,語言中用和這三個狀態分別表示。 前文回顧 上一篇文章重點嘮叨了java中協調線程間通信的wait/notify機制,它有力的保證了線程間通信的安全性以及便利性。本篇將介紹wait/notify機制的一個應用...

    lufficc 評論0 收藏0
  • Java 線程核心技術梳理(附源碼)

    摘要:本文對多線程基礎知識進行梳理,主要包括多線程的基本使用,對象及變量的并發訪問,線程間通信,的使用,定時器,單例模式,以及線程狀態與線程組。源碼采用構建,多線程這部分源碼位于模塊中。通知可能等待該對象的對象鎖的其他線程。 本文對多線程基礎知識進行梳理,主要包括多線程的基本使用,對象及變量的并發訪問,線程間通信,lock的使用,定時器,單例模式,以及線程狀態與線程組。 寫在前面 花了一周時...

    Winer 評論0 收藏0
  • Java基礎線程Thread

    摘要:在程序開發中一定遇到并發編程的場景雖然我們大部分時間并不直接使用但是是多線程的基礎面試中也會總是被問到與線程有關的問題那么線程都有哪些知識呢最近在研究線程的源碼的時候也總結了關于線程一些基本知識線程是什么線程是輕量級的進程是操作系統調度任務 在程序開發中, 一定遇到并發編程的場景, 雖然我們大部分時間并不直接使用Thread, 但是Thread是多線程的基礎, 面試中也會總是被問到與線...

    tomlingtm 評論0 收藏0

發表評論

0條評論

最新活動
閱讀需要支付1元查看
<