亚洲中字慕日产2020,大陆极品少妇内射AAAAAA,无码av大香线蕉伊人久久,久久精品国产亚洲av麻豆网站

資訊專(zhuān)欄INFORMATION COLUMN

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

eccozhou / 3385人閱讀

摘要:和簡(jiǎn)介和均為的方法暫停一個(gè)線程喚醒一個(gè)線程從以上的定義中,我們可以了解到以下事實(shí)想要使用這兩個(gè)方法,我們需要先有一個(gè)對(duì)象。在中任何一個(gè)時(shí)刻,對(duì)象的控制權(quán)只能被一個(gè)線程擁有。若有多個(gè)線程處于此控制權(quán)下的狀態(tài),只有一個(gè)會(huì)被喚醒。

最近看帖子,發(fā)現(xiàn)一道面試題:

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

題目要求用 Java 的 wait + notify 機(jī)制來(lái)實(shí)現(xiàn),重點(diǎn)考察對(duì)于多線程可見(jiàn)性的理解。

wait 和 notify 簡(jiǎn)介

wait 和 notify 均為 Object 的方法:

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

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

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

想要使用這兩個(gè)方法,我們需要先有一個(gè)對(duì)象 Object。

在多個(gè)線程之間,我們可以通過(guò)調(diào)用同一個(gè)對(duì)象wait()notify()來(lái)實(shí)現(xiàn)不同的線程間的可見(jiàn)。

對(duì)象控制權(quán)(monitor)

在使用 wait 和 notify 之前,我們需要先了解對(duì)象的控制權(quán)(monitor)。在 Java 中任何一個(gè)時(shí)刻,對(duì)象的控制權(quán)只能被一個(gè)線程擁有。如何理解控制權(quán)呢?請(qǐng)先看下面的簡(jiǎn)單代碼:

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();
    }
}

直接執(zhí)行,我們將會(huì)得到以下異常:

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)

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

無(wú)論是執(zhí)行對(duì)象的 wait、notify 還是 notifyAll 方法,必須保證當(dāng)前運(yùn)行的線程取得了該對(duì)象的控制權(quán)(monitor)

如果在沒(méi)有控制權(quán)的線程里執(zhí)行對(duì)象的以上三種方法,就會(huì)報(bào) java.lang.IllegalMonitorStateException 異常。

JVM 基于多線程,默認(rèn)情況下不能保證運(yùn)行時(shí)線程的時(shí)序性

在上面的示例代碼中,我們 new 了一個(gè) Thread,但是對(duì)象 object 的控制權(quán)仍在主線程里。所以會(huì)報(bào) java.lang.IllegalMonitorStateException 。

我們可以通過(guò)同步鎖來(lái)獲得對(duì)象控制權(quán),例如:synchronized 代碼塊。對(duì)以上的示例代碼做改造:

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();
    }
}

再次執(zhí)行,代碼不再報(bào)錯(cuò)。

我們可以得到以下結(jié)論:

調(diào)用對(duì)象的wait()notify()方法,需要先取得對(duì)象的控制權(quán)

可以使用synchronized (object)來(lái)取得對(duì)于 object 對(duì)象的控制權(quán)

解題

了解了對(duì)象控制權(quán)之后,我們就可以正常地使用 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();
                    }
                }
            }
        }
    }
}
發(fā)散:notify()notifyAll()

這兩個(gè)方法均為 native 方法,在JDK 1.8 中的關(guān)于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 控制權(quán)下的一個(gè)處于 wait 狀態(tài)的線程。若有多個(gè)線程處于此 object 控制權(quán)下的 wait 狀態(tài),只有一個(gè)會(huì)被喚醒。

也就是說(shuō),如果有多個(gè)線程在 wait 狀態(tài),我們并不知道哪個(gè)線程會(huì)被喚醒。

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

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

譯為:

喚醒所有處于此 object 控制權(quán)下的 wait 狀態(tài)的線程。

所以,我們需要根據(jù)實(shí)際的業(yè)務(wù)場(chǎng)景來(lái)考慮如何使用。

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://www.ezyhdfw.cn/yun/77389.html

相關(guān)文章

  • java并發(fā)編程學(xué)習(xí)線程的生命周期-wait,notify,notifyall(六)

    摘要:不釋放持有的鎖,釋放鎖。在調(diào)用方法前,必須持有鎖,調(diào)用喚醒,也要持有鎖。休眠一定時(shí)間后,進(jìn)入就緒狀態(tài)。這兩個(gè)都能被方法中斷當(dāng)前狀態(tài)。用法方獲取鎖判斷條件,不滿足繼續(xù)滿足執(zhí)行其他業(yè)務(wù)方獲取鎖改變條件通知為什么是而不是會(huì)一直循環(huán),直到條件滿足。 sleep和wait sleep是Thread類(lèi)的方法,wait是Object的方法。 sleep可以到處使用,wait必須是在同步方法或者代碼...

    Terry_Tai 評(píng)論0 收藏0
  • Java并發(fā)編程線程間通訊(上)wait/notify機(jī)制

    摘要:用線程表示維修的過(guò)程維修結(jié)束把廁所置為可用狀態(tài)維修工把廁所修好了,準(zhǔn)備釋放鎖了這個(gè)維修計(jì)劃的內(nèi)容就是當(dāng)維修工進(jìn)入廁所之后,先把門(mén)鎖上,然后開(kāi)始維修,維修結(jié)束之后把的字段設(shè)置為,以表示廁所可用。 線程間通信 如果一個(gè)線程從頭到尾執(zhí)行完也不和別的線程打交道的話,那就不會(huì)有各種安全性問(wèn)題了。但是協(xié)作越來(lái)越成為社會(huì)發(fā)展的大勢(shì),一個(gè)大任務(wù)拆成若干個(gè)小任務(wù)之后,各個(gè)小任務(wù)之間可能也需要相互協(xié)作最終...

    Lionad-Morotar 評(píng)論0 收藏0
  • Java并發(fā)編程線程間通訊(下)-生產(chǎn)者與消費(fèi)者

    摘要:前文回顧上一篇文章重點(diǎn)嘮叨了中協(xié)調(diào)線程間通信的機(jī)制,它有力的保證了線程間通信的安全性以及便利性。所以同一時(shí)刻廚師線程和服務(wù)員線程不會(huì)同時(shí)在等待隊(duì)列中。對(duì)于在操作系統(tǒng)中線程的阻塞狀態(tài),語(yǔ)言中用和這三個(gè)狀態(tài)分別表示。 前文回顧 上一篇文章重點(diǎn)嘮叨了java中協(xié)調(diào)線程間通信的wait/notify機(jī)制,它有力的保證了線程間通信的安全性以及便利性。本篇將介紹wait/notify機(jī)制的一個(gè)應(yīng)用...

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

    摘要:本文對(duì)多線程基礎(chǔ)知識(shí)進(jìn)行梳理,主要包括多線程的基本使用,對(duì)象及變量的并發(fā)訪問(wèn),線程間通信,的使用,定時(shí)器,單例模式,以及線程狀態(tài)與線程組。源碼采用構(gòu)建,多線程這部分源碼位于模塊中。通知可能等待該對(duì)象的對(duì)象鎖的其他線程。 本文對(duì)多線程基礎(chǔ)知識(shí)進(jìn)行梳理,主要包括多線程的基本使用,對(duì)象及變量的并發(fā)訪問(wèn),線程間通信,lock的使用,定時(shí)器,單例模式,以及線程狀態(tài)與線程組。 寫(xiě)在前面 花了一周時(shí)...

    Winer 評(píng)論0 收藏0
  • Java基礎(chǔ)線程Thread

    摘要:在程序開(kāi)發(fā)中一定遇到并發(fā)編程的場(chǎng)景雖然我們大部分時(shí)間并不直接使用但是是多線程的基礎(chǔ)面試中也會(huì)總是被問(wèn)到與線程有關(guān)的問(wèn)題那么線程都有哪些知識(shí)呢最近在研究線程的源碼的時(shí)候也總結(jié)了關(guān)于線程一些基本知識(shí)線程是什么線程是輕量級(jí)的進(jìn)程是操作系統(tǒng)調(diào)度任務(wù) 在程序開(kāi)發(fā)中, 一定遇到并發(fā)編程的場(chǎng)景, 雖然我們大部分時(shí)間并不直接使用Thread, 但是Thread是多線程的基礎(chǔ), 面試中也會(huì)總是被問(wèn)到與線...

    tomlingtm 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

閱讀需要支付1元查看
<