国产精品电影_久久视频免费_欧美日韩国产激情_成年人视频免费在线播放_日本久久亚洲电影_久久都是精品_66av99_九色精品美女在线_蜜臀a∨国产成人精品_冲田杏梨av在线_欧美精品在线一区二区三区_麻豆mv在线看

Java并發(fā)編程:使用Wait和Notify方法的注意事項(xiàng)

開(kāi)發(fā) 前端
save?方法負(fù)責(zé)向緩沖區(qū)添加數(shù)據(jù),然后執(zhí)行notify?方法來(lái)喚醒之前等待的線(xiàn)程。take方法負(fù)責(zé)檢查緩沖區(qū)是否為空。如果為空,線(xiàn)程進(jìn)入等待狀態(tài);如果不為空,線(xiàn)程從緩沖區(qū)中取出數(shù)據(jù)。

在之前的講解線(xiàn)程狀態(tài)的文章中,我們提到了wait和notify方法可以讓線(xiàn)程在運(yùn)行狀態(tài)和等待狀態(tài)之間轉(zhuǎn)換。在這篇文章中,我們將深入探討wait、notify和notifyAll方法在使用中的注意事項(xiàng)。我們主要從三個(gè)問(wèn)題入手:

  • 為什么wait方法必須在synchronized保護(hù)的代碼中使用?
  • 為什么wait方法需要在循環(huán)操作中使用?
  • wait/notify和sleep方法有什么異同?

1. 為什么wait()方法必須在synchronized修飾的代碼中使用?

為了找到這個(gè)問(wèn)題的答案,我們不妨反過(guò)來(lái)思考:如果不要求在synchronized代碼中使用wait方法,會(huì)出現(xiàn)什么問(wèn)題呢?讓我們來(lái)看這段代碼。

public class QueueDemo {
    Queue<String> buffer = new LinkedList<String>();
    public void save(String data) {
        buffer.add(data);
        notify(); // 因?yàn)榭赡苡芯€(xiàn)程在 take() 方法中等待
    }

    public String take() throws InterruptedException {
        while (buffer.isEmpty()) {
            wait();
        }
        return buffer.remove();
    }
}

在這段代碼中,有兩個(gè)方法。save方法負(fù)責(zé)向緩沖區(qū)添加數(shù)據(jù),然后執(zhí)行notify方法來(lái)喚醒之前等待的線(xiàn)程。take方法負(fù)責(zé)檢查緩沖區(qū)是否為空。如果為空,線(xiàn)程進(jìn)入等待狀態(tài);如果不為空,線(xiàn)程從緩沖區(qū)中取出數(shù)據(jù)。

這段代碼沒(méi)有使用synchronized保護(hù),可能會(huì)出現(xiàn)以下情況:

  • 首先,消費(fèi)者線(xiàn)程調(diào)用take方法,并判斷buffer.isEmpty是否返回true。如果返回true,表示緩沖區(qū)為空,線(xiàn)程準(zhǔn)備進(jìn)入等待狀態(tài)。然而,在線(xiàn)程調(diào)用wait方法之前,它被可能已經(jīng)被掛起了,wait方法沒(méi)有執(zhí)行。
  • 此時(shí),生產(chǎn)者線(xiàn)程開(kāi)始運(yùn)行,并執(zhí)行了整個(gè)save方法。它向緩沖區(qū)添加了數(shù)據(jù),并執(zhí)行了notify方法,但notify沒(méi)有效果,因?yàn)橄M(fèi)者線(xiàn)程的wait方法還沒(méi)有執(zhí)行,所以沒(méi)有線(xiàn)程在等待被喚醒。
  • 隨后,之前被掛起的消費(fèi)者線(xiàn)程恢復(fù)執(zhí)行,并調(diào)用了wait方法,進(jìn)入等待狀態(tài)。

出現(xiàn)這個(gè)問(wèn)題的原因是這里的“判斷 - 執(zhí)行”不是原子操作,它在中間被中斷,是線(xiàn)程不安全的。

假設(shè)此時(shí)沒(méi)有更多的生產(chǎn)者進(jìn)行生產(chǎn),消費(fèi)者可能會(huì)陷入無(wú)限等待,因?yàn)樗e(cuò)過(guò)了save方法中的notify喚醒。

你可以模擬一個(gè)生產(chǎn)者線(xiàn)程和一個(gè)消費(fèi)者線(xiàn)程分別調(diào)用這兩個(gè)方法:

public class QueueDemo2 {
    Queue<String> buffer = new LinkedList<>();
    public void save(String data) {
        System.out.println("Produce a data");
        buffer.add(data);
        notify(); // 因?yàn)榭赡苡腥嗽?take() 中等待
    }
    public String take() throws InterruptedException {
        System.out.println("Try to consume a data");
        while (buffer.isEmpty()) {
            wait();
        }
        return buffer.remove();
    }
    public static void main(String[] args) throws InterruptedException {
        QueueDemo2 queueDemo = new QueueDemo2();
        Thread producerThread = new Thread(() -> {
            queueDemo.save("Hello World!");
        });
        Thread consumerThread = new Thread(() -> {
            try {
                System.out.println(queueDemo.take());
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        });
        consumerThread.start();
        producerThread.start();
    }
}

你可以嘗試執(zhí)行這段代碼,看看是否會(huì)出現(xiàn)之前提到的問(wèn)題。

實(shí)際輸出如下:

Try to consume a data
Produce a data
Exception in thread "Thread-0" Exception in thread "Thread-1"
java.lang.IllegalMonitorStateException
    at java.lang.Object.notify(Native Method)
    at thread.basic.chapter4.QueueDemo2.save(QueueDemo2.java:13)
    at thread.basic.chapter4.QueueDemo2.lambda$main$0(QueueDemo2.java:28)
    at java.lang.Thread.run(Thread.java:748)
java.lang.IllegalMonitorStateException
    at java.lang.Object.wait(Native Method)
    at java.lang.Object.wait(Object.java:502)
    at thread.basic.chapter4.QueueDemo2.take(QueueDemo2.java:19)
    at thread.basic.chapter4.QueueDemo2.lambda$main$1(QueueDemo2.java:33)

根本沒(méi)有犯錯(cuò)的機(jī)會(huì)。wait方法和notify方法在沒(méi)有synchronized保護(hù)的代碼塊中執(zhí)行時(shí),會(huì)直接拋出java.lang.IllegalMonitorStateException異常。

修改代碼:

public class SyncQueueDemo2 {
    Queue<String> buffer = new LinkedList<>();
    public synchronized void save(String data) {
        System.out.println("Produce a data");
        buffer.add(data);
        notify(); // 因?yàn)榭赡苡腥嗽?take() 中等待
    }
    public synchronized String take() throws InterruptedException {
        System.out.println("Try to consume a data");
        while (buffer.isEmpty()) {
            wait();
        }
        return buffer.remove();
    }
    public static void main(String[] args) throws InterruptedException {
        SyncQueueDemo2 queueDemo = new SyncQueueDemo2();
        Thread producerThread = new Thread(() -> {
            queueDemo.save("Hello World!");
        });
        Thread consumerThread = new Thread(() -> {
            try {
                System.out.println(queueDemo.take());
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        });
        consumerThread.start();
        producerThread.start();
    }
}

再次執(zhí)行代碼,輸出如下:

Produce a data
Try to consume a data
Hello World!

可以看到,生產(chǎn)的"Hello World!"已經(jīng)被成功消費(fèi)并打印到控制臺(tái)。

2. 為什么wait方法需要在循環(huán)操作中使用?

線(xiàn)程調(diào)用wait方法后,可能會(huì)出現(xiàn)虛假喚醒(spurious wakeup)的情況,即線(xiàn)程在沒(méi)有被notify/notifyAll調(diào)用、沒(méi)有被中斷、也沒(méi)有超時(shí)的情況下被喚醒,這是我們不希望發(fā)生的情況。

雖然在真實(shí)環(huán)境中,虛假喚醒的概率非常小,但程序仍然需要在虛假喚醒的情況下保證正確性,因此需要使用while循環(huán)結(jié)構(gòu)。

while (條件不滿(mǎn)足) {
    obj.wait();
}

這樣,即使線(xiàn)程被虛假喚醒,如果條件不滿(mǎn)足,wait會(huì)繼續(xù)執(zhí)行,從而消除虛假喚醒導(dǎo)致的風(fēng)險(xiǎn)。

3.wait/notify和sleep方法有什么異同?

wait方法和sleep方法的相同點(diǎn)如下:

  • 它們都可以阻塞線(xiàn)程。
  • 它們都可以響應(yīng)中斷:如果在等待過(guò)程中收到中斷信號(hào),它們會(huì)響應(yīng)并拋出InterruptedException異常。

它們之間也有很多不同點(diǎn):

  • wait方法必須在synchronized保護(hù)的代碼中使用,而sleep方法沒(méi)有這個(gè)要求。
  • 當(dāng)sleep方法在synchronized代碼中執(zhí)行時(shí),它不會(huì)釋放鎖,而wait方法會(huì)主動(dòng)釋放鎖。
  • sleep方法需要定義一個(gè)時(shí)間,時(shí)間到期后線(xiàn)程會(huì)主動(dòng)恢復(fù)。對(duì)于沒(méi)有參數(shù)的wait方法,它意味著永久等待,直到被中斷或喚醒,不會(huì)主動(dòng)恢復(fù)。
  • wait和notify是Object類(lèi)的方法,而sleep是Thread類(lèi)的方法。

好了,這次的內(nèi)容就到這里,下次再見(jiàn)!

責(zé)任編輯:武曉燕 來(lái)源: 程序猿技術(shù)充電站
相關(guān)推薦

2021-07-10 08:37:36

Notify機(jī)制Java

2022-09-23 09:25:04

代碼方法

2009-06-12 09:46:40

Java String

2010-03-15 18:25:27

Java編程語(yǔ)言

2009-09-01 17:25:33

初學(xué)C#編程

2010-11-26 16:27:01

MySQL使用變量

2009-08-27 10:40:56

Java路徑

2023-12-12 09:06:06

2011-06-23 11:15:25

SEO網(wǎng)站優(yōu)化

2024-02-01 09:39:02

asyncawaitPromise

2010-08-12 09:39:26

FlexaddChil

2012-03-12 16:46:22

NoSQL數(shù)據(jù)庫(kù)

2011-07-28 17:29:22

HBaseShell

2011-05-26 11:22:04

SEO

2009-06-11 17:52:08

JavaBean

2009-06-25 14:41:06

JavaBean

2015-08-05 09:33:21

Javawaitnotify

2010-01-21 11:30:10

2021-12-20 23:22:46

Java開(kāi)發(fā)升級(jí)

2011-03-22 08:56:30

點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)

亚洲国产精品传媒在线观看| www 日韩| 暴力调教一区二区三区| 色欧美日韩亚洲| 国产精品一区二区三区精品| а√在线中文在线新版| 99re视频精品| 蜜桃免费在线| 日韩亚洲欧美一区| 久久免费一级片| bt欧美亚洲午夜电影天堂| 国产精品一区二区三区免费观看| 黄色欧美在线| 日韩毛片中文字幕| 精品丰满人妻无套内射| 久久精品国产精品亚洲综合| 38少妇精品导航| 特级西西444| 四虎精品永久免费| 欧美v国产在线一区二区三区| 亚洲精品成人| 99久re热视频精品98| 日韩在线一区二区三区| www.黄色网址.com| 欧美激情20| 92福利视频午夜1000合集在线观看| 妖精视频一区二区三区| 精品日韩在线| 久久久精品一区二区三区| 国产白丝在线观看| 欧美高清dvd| 国产黄色免费在线观看| 亚洲色欲色欲www在线观看| 毛片毛片毛片毛片毛片毛片毛片毛片毛片| 国内成人自拍视频| 视频在线99| 日韩精品欧美成人高清一区二区| 国产情人节一区| 欧美一区二区三区激情视频 | 777米奇影视第四色| 国产在线看一区| 亚洲一卡二卡| 蜜臀精品一区二区三区在线观看| 日本在线高清视频一区| 精品一区二区三区蜜桃| 女同性恋一区二区| 99精品国产视频| 天天干天天综合| 一区二区三区美女| 在线观看一级片| 欧美亚洲图片小说| 羞羞污视频在线观看| 亚洲免费电影在线观看| 欧美极品在线| 97在线看福利| 一二三区不卡| 欧美一区二区三区四区在线观看地址 | 黑人久久a级毛片免费观看| 午夜精品久久久久久久99热浪潮| 国产精品网址| 国产精品中文在线| 亚洲天堂激情| 99精品视频网站| 久久婷婷色综合| 在线播放国产区| 欧美电影影音先锋| 欧美高清影院| 国产精品偷伦视频免费观看国产| 欧美三区在线| 欧美 亚洲 视频| 亚洲色欲色欲www在线观看| 国产日本在线视频| 亚洲欧美在线免费观看| 精品网站aaa| 99久久一区三区四区免费| 免费观看日韩av| 色播五月综合网| 欧美性色黄大片| 黑人一区二区三区| 国产一区二区丝袜高跟鞋图片| 先锋影音久久| 欧美三级一级片| 色综合中文字幕| a一区二区三区| 国产精品久久久久久av福利| 日本成人中文字幕在线视频 | 免费看的黄色大片| 午夜视频一区二区三区| 日韩精品分区| 亚洲 日韩 国产第一| 亚洲国产一区二区三区高清| 欧美一级片免费播放| 欧美日韩一区免费| 欧美日韩女优| 91在线精品观看| 99精品视频在线免费观看| 国产精品精华液网站| 亚洲精品在线视频| 色88久久久久高潮综合影院| 超碰97在线看| 色综合久久88色综合天天免费| 快播电影网址老女人久久| 91精品视频在线播放| 成人综合激情网| 97超碰人人在线| 亚州欧美日韩中文视频| 久久精品国产精品亚洲综合| 久草在线在线| 欧美成人网在线| 蜜桃视频在线观看一区| 在线看片线路1| 久久久久久国产免费| 免费成人你懂的| 日本不卡视频一区二区| 午夜精品一区二区三区在线 | 精品免费视频.| jlzzjlzz亚洲女人| 国产中文字幕乱人伦在线观看| 欧美伊人久久久久久久久影院| 精品一区二区三区亚洲| 亚洲一卡二卡| 欧美日韩一区二区在线观看 | 欧美理论一区二区| 一片黄亚洲嫩模| 精品国产乱码久久久久久樱花| 日韩欧美电影一区二区| 91九色02白丝porn| 成人一区不卡| 99热在线观看| 九九九久久国产免费| 国产乱码精品一区二区三| 国产网站在线免费观看| 51国产成人精品午夜福中文下载| 一区在线中文字幕| 免费看日产一区二区三区| 91xxx视频| 精品卡一卡二卡三卡四在线| 亚洲国内欧美| 日本大臀精品| 国产免费一区视频观看免费 | 超碰aⅴ人人做人人爽欧美| 国产一区二区无遮挡| 精品福利在线看| 国产精品免费不| caoliu在线| 日本韩国在线不卡| 亚洲欧美日韩一区| 国产精品一区二区三区美女| 久久无码高潮喷水| 少妇高潮 亚洲精品| 丁香婷婷综合网| 亚洲精品555| 国产一区二区视频播放| 亚洲午夜av久久乱码| 国产xxx精品视频大全| 成人国产一区| 精品国产成人av在线免| 欧美激情精品久久久久久蜜臀| 国产区在线观看成人精品| 操欧美女人视频| 人与动性xxxxx免费视频| 全球成人中文在线| 黄网站色欧美视频| 亚洲黄色视屏| 91老司机福利在线| 日韩久久久久久久久久久久| 国产偷亚洲偷欧美偷精品| 国产精品一区二区免费不卡| 99精品国自产在线| 91在线视频观看免费| 日本精品久久久久久久| 欧美日韩美女在线| 日韩一级精品| 欧美日韩在线精品一区二区三区激情综合| 91精品福利观看| 国产精品裸体瑜伽视频| 欧美高清videos高潮hd| 亚洲色图制服诱惑| 极品尤物久久久av免费看| 免费影视亚洲| 色综合av综合无码综合网站| 欧日韩在线观看| 欧美三级蜜桃2在线观看| 美女在线视频一区| 玖玖玖电影综合影院| 久草在线中文888| 欧美精品久久| 久久网福利资源网站| 一区二区不卡在线播放| 尤物精品在线| 国精产品一区一区三区四川| 国产成人久久777777| 成人av资源在线播放| 精品久久久久久久久久久久久久久久久 | 欧美日韩天天操| 中文字幕日韩高清| 亚洲午夜三级在线| 日韩精品一级中文字幕精品视频免费观看| 亚洲成人看片| 二个人看的毛片|