成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專欄INFORMATION COLUMN

Java? 教程(守護(hù)阻塞)

ivyzhang / 1400人閱讀

守護(hù)阻塞

線程通常必須協(xié)調(diào)他們的操作,最常見的協(xié)調(diào)用法是守護(hù)阻塞,這樣的阻塞首先輪詢一個(gè)條件,該條件必須為真,然后阻塞才能繼續(xù),要正確執(zhí)行此操作,需要執(zhí)行許多步驟。

例如,假設(shè)guardedJoy是一個(gè)方法,在另一個(gè)線程設(shè)置了共享變量joy之前,該方法不能繼續(xù),理論上,這種方法可以簡單地循環(huán)直到滿足條件,但該循環(huán)是浪費(fèi)的,因?yàn)樗诘却龝r(shí)持續(xù)執(zhí)行。

public void guardedJoy() {
    // Simple loop guard. Wastes
    // processor time. Don"t do this!
    while(!joy) {}
    System.out.println("Joy has been achieved!");
}

更有效的守護(hù)是調(diào)用Object.wait來掛起當(dāng)前線程,在另一個(gè)線程發(fā)出可能發(fā)生某些特殊事件的通知之前,wait的調(diào)用不會(huì)返回 — 盡管不一定是這個(gè)線程正在等待的事件:

public synchronized void guardedJoy() {
    // This guard only loops once for each special event, which may not
    // be the event we"re waiting for.
    while(!joy) {
        try {
            wait();
        } catch (InterruptedException e) {}
    }
    System.out.println("Joy and efficiency have been achieved!");
}
始終在測試等待條件的循環(huán)內(nèi)調(diào)用wait,不要假設(shè)中斷是針對(duì)你正在等待的特定條件,或者條件仍然是true。

像許多暫停執(zhí)行的方法一樣,wait會(huì)拋出InterruptedException,在這個(gè)例子中,我們可以忽略該異常 — 我們只關(guān)心joy的值。

為什么這個(gè)版本的guardedJoy是同步的?假設(shè)d是我們用來調(diào)用wait的對(duì)象,當(dāng)一個(gè)線程調(diào)用d.wait時(shí),它必須擁有d的固有鎖 — 否則拋出一個(gè)錯(cuò)誤,在同步方法中調(diào)用wait是獲取固有鎖的一種簡單方法。

當(dāng)調(diào)用wait時(shí),線程釋放鎖并暫停執(zhí)行,在將來的某個(gè)時(shí)間,另一個(gè)線程將獲取相同的鎖并調(diào)用Object.notifyAll,通知等待該鎖的所有線程發(fā)生了重要的事情:

public synchronized notifyJoy() {
    joy = true;
    notifyAll();
}

在第二個(gè)線程釋放鎖之后的一段時(shí)間,第一個(gè)線程重新獲取鎖并通過從調(diào)用wait的返回來恢復(fù)。

還有第二種通知方法notify,它喚醒單個(gè)線程,因?yàn)?b>notify不允許你指定被喚醒的線程,所以它僅在大規(guī)模并行應(yīng)用程序中有用 — 也就是說,具有大量線程的程序,都做類似的事,在這樣的應(yīng)用程序中,你不關(guān)心哪個(gè)線程被喚醒。

讓我們使用守護(hù)阻塞來創(chuàng)建生產(chǎn)者—消費(fèi)者應(yīng)用程序,這種應(yīng)用程序在兩個(gè)線程之間共享數(shù)據(jù):創(chuàng)建數(shù)據(jù)的生產(chǎn)者和使用數(shù)據(jù)的消費(fèi)者。兩個(gè)線程使用共享對(duì)象進(jìn)行通信,協(xié)調(diào)至關(guān)重要:消費(fèi)者線程在生產(chǎn)者線程交付之前不得嘗試檢索數(shù)據(jù),如果消費(fèi)者未檢索到舊數(shù)據(jù),則生產(chǎn)者線程不得嘗試傳遞新數(shù)據(jù)。

在此示例中,數(shù)據(jù)是一系列文本消息,通過Drop類型的對(duì)象共享:

public class Drop {
    // Message sent from producer
    // to consumer.
    private String message;
    // True if consumer should wait
    // for producer to send message,
    // false if producer should wait for
    // consumer to retrieve message.
    private boolean empty = true;

    public synchronized String take() {
        // Wait until message is
        // available.
        while (empty) {
            try {
                wait();
            } catch (InterruptedException e) {}
        }
        // Toggle status.
        empty = true;
        // Notify producer that
        // status has changed.
        notifyAll();
        return message;
    }

    public synchronized void put(String message) {
        // Wait until message has
        // been retrieved.
        while (!empty) {
            try { 
                wait();
            } catch (InterruptedException e) {}
        }
        // Toggle status.
        empty = false;
        // Store message.
        this.message = message;
        // Notify consumer that status
        // has changed.
        notifyAll();
    }
}

Producer中定義的生產(chǎn)者線程發(fā)送一系列熟悉的消息,字符串“DONE”表示已發(fā)送所有消息,為了模擬真實(shí)世界應(yīng)用程序的不可預(yù)測性,生產(chǎn)者線程在消息發(fā)送之間暫停隨機(jī)間隔。

import java.util.Random;

public class Producer implements Runnable {
    private Drop drop;

    public Producer(Drop drop) {
        this.drop = drop;
    }

    public void run() {
        String importantInfo[] = {
            "Mares eat oats",
            "Does eat oats",
            "Little lambs eat ivy",
            "A kid will eat ivy too"
        };
        Random random = new Random();

        for (int i = 0;
             i < importantInfo.length;
             i++) {
            drop.put(importantInfo[i]);
            try {
                Thread.sleep(random.nextInt(5000));
            } catch (InterruptedException e) {}
        }
        drop.put("DONE");
    }
}

在Consumer中定義的消費(fèi)者線程只是檢索消息并將其打印出來,直到它檢索到“DONE”字符串,該線程也會(huì)暫停隨機(jī)間隔。

import java.util.Random;

public class Consumer implements Runnable {
    private Drop drop;

    public Consumer(Drop drop) {
        this.drop = drop;
    }

    public void run() {
        Random random = new Random();
        for (String message = drop.take();
             ! message.equals("DONE");
             message = drop.take()) {
            System.out.format("MESSAGE RECEIVED: %s%n", message);
            try {
                Thread.sleep(random.nextInt(5000));
            } catch (InterruptedException e) {}
        }
    }
}

最后,這是在ProducerConsumerExample中定義的主線程,它啟動(dòng)生產(chǎn)者和消費(fèi)者線程。

public class ProducerConsumerExample {
    public static void main(String[] args) {
        Drop drop = new Drop();
        (new Thread(new Producer(drop))).start();
        (new Thread(new Consumer(drop))).start();
    }
}
Drop類是為了演示守護(hù)阻塞而編寫的,為了避免重新造輪子,在嘗試編寫自己的數(shù)據(jù)共享對(duì)象之前,檢查Java集合框架中的現(xiàn)有數(shù)據(jù)結(jié)構(gòu)。
上一篇:并發(fā)活性 下一篇:不可變對(duì)象

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

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

相關(guān)文章

  • Java? 教程(并發(fā)活性)

    并發(fā)活性 并發(fā)應(yīng)用程序及時(shí)執(zhí)行的能力被稱為其活性,本節(jié)描述了最常見的活性問題,死鎖,并繼續(xù)簡要描述其他兩個(gè)活性問題,饑餓和活鎖。 死鎖 死鎖描述了兩個(gè)或多個(gè)線程永遠(yuǎn)被阻塞,等待彼此的情況,這是一個(gè)例子。 Alphonse和Gaston是朋友,是禮貌的忠實(shí)信徒,禮貌的一個(gè)嚴(yán)格規(guī)則是,當(dāng)你向朋友鞠躬時(shí),你必須一直鞠躬,直到你的朋友有機(jī)會(huì)還禮,不幸的是,這條規(guī)則沒有考慮到兩個(gè)朋友可能同時(shí)互相鞠躬的可能性...

    KaltZK 評(píng)論0 收藏0
  • JAVA 多線程和并發(fā)基礎(chǔ)面試問答

    摘要:多線程和并發(fā)問題是技術(shù)面試中面試官比較喜歡問的問題之一。線程可以被稱為輕量級(jí)進(jìn)程。一個(gè)守護(hù)線程是在后臺(tái)執(zhí)行并且不會(huì)阻止終止的線程。其他的線程狀態(tài)還有,和。上下文切換是多任務(wù)操作系統(tǒng)和多線程環(huán)境的基本特征。 多線程和并發(fā)問題是 Java 技術(shù)面試中面試官比較喜歡問的問題之一。在這里,從面試的角度列出了大部分重要的問題,但是你仍然應(yīng)該牢固的掌握J(rèn)ava多線程基礎(chǔ)知識(shí)來對(duì)應(yīng)日后碰到的問題。(...

    dreamans 評(píng)論0 收藏0
  • JAVA 多線程和并發(fā)基礎(chǔ)

    摘要:線程可以被稱為輕量級(jí)進(jìn)程。一個(gè)守護(hù)線程是在后臺(tái)執(zhí)行并且不會(huì)阻止終止的線程。其他的線程狀態(tài)還有,和。上下文切換是多任務(wù)操作系統(tǒng)和多線程環(huán)境的基本特征。在的線程中并沒有可供任何對(duì)象使用的鎖和同步器。 原文:Java Multi-Threading and Concurrency Interview Questions with Answers 翻譯:并發(fā)編程網(wǎng) - 鄭旭東 校對(duì):方騰飛 多...

    vboy1010 評(píng)論0 收藏0
  • 慕課網(wǎng)_《細(xì)說多線程之Thread VS Runnable》學(xué)習(xí)總結(jié)

    摘要:時(shí)間年月日星期六說明本文部分內(nèi)容均來自慕課網(wǎng)。慕課網(wǎng)教學(xué)源碼無學(xué)習(xí)源碼第一章課前準(zhǔn)備前言課程說明比較和這兩種線程創(chuàng)建的方式,需要知道和的基本創(chuàng)建方式。一旦主線程獲取到了用戶的輸入,這時(shí)候,阻塞就會(huì)解除掉,主線程繼續(xù)運(yùn)行,直到結(jié)束。 時(shí)間:2017年07月08日星期六說明:本文部分內(nèi)容均來自慕課網(wǎng)。@慕課網(wǎng):http://www.imooc.com教學(xué)源碼:無學(xué)習(xí)源碼:https://g...

    netScorpion 評(píng)論0 收藏0
  • @Java | Thread & synchronized - [ 多線程 理論知識(shí)]

    摘要:死亡線程方法執(zhí)行結(jié)束,或者因異常退出了方法,則該線程結(jié)束生命周期。死亡的線程不可再次復(fù)生。直到當(dāng)前的線程放棄此對(duì)象上的鎖定,才能繼續(xù)執(zhí)行被喚醒的線程。枚舉程序中的線程。強(qiáng)迫一個(gè)線程等待。通知一個(gè)線程繼續(xù)運(yùn)行。 一. 線程狀態(tài)轉(zhuǎn)換圖 showImg(https://segmentfault.com/img/bV38ef?w=968&h=680); 線程間的狀態(tài)轉(zhuǎn)換說明: 新建(new)...

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

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

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<