最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Java并發(fā)編程之線程間的通信

 更新時(shí)間:2021年06月18日 12:01:22   作者:知了一笑  
當(dāng)線程在系統(tǒng)內(nèi)運(yùn)行時(shí),程序通常無(wú)法準(zhǔn)確的控制線程的輪換執(zhí)行,但我們可以通過(guò)一些機(jī)制來(lái)保障線程的協(xié)調(diào)運(yùn)行,本文著重講解線程間的通信機(jī)制

一、概念簡(jiǎn)介

1、線程通信

在操作系統(tǒng)中,線程是個(gè)獨(dú)立的個(gè)體,但是在線程執(zhí)行過(guò)程中,如果處理同一個(gè)業(yè)務(wù)邏輯,可能會(huì)產(chǎn)生資源爭(zhēng)搶?zhuān)瑢?dǎo)致并發(fā)問(wèn)題,通常使用互斥鎖來(lái)控制該邏輯。但是在還有這樣一類(lèi)場(chǎng)景,任務(wù)執(zhí)行是有順序控制的,例如常見(jiàn)的報(bào)表數(shù)據(jù)生成:

  • 啟動(dòng)數(shù)據(jù)分析任務(wù),生成報(bào)表數(shù)據(jù);
  • 報(bào)表數(shù)據(jù)存入指定位置數(shù)據(jù)容器;
  • 通知數(shù)據(jù)搬運(yùn)任務(wù),把數(shù)據(jù)寫(xiě)入報(bào)表庫(kù);

該場(chǎng)景在相對(duì)復(fù)雜的系統(tǒng)中非常常見(jiàn),如果基于多線程來(lái)描述該過(guò)程,則需要線程之間通信協(xié)作,才能有條不紊的處理該場(chǎng)景業(yè)務(wù)。

2、等待通知機(jī)制

如上的業(yè)務(wù)場(chǎng)景,如果線程A生成數(shù)據(jù)過(guò)程中,線程B一直在訪問(wèn)數(shù)據(jù)容器,判斷該過(guò)程的數(shù)據(jù)是否已經(jīng)生成,則會(huì)造成資源浪費(fèi)。正常的流程應(yīng)該如圖,線程A和線程B同時(shí)啟動(dòng),線程A開(kāi)始處理數(shù)據(jù)生成任務(wù),線程B嘗試獲取容器數(shù)據(jù),數(shù)據(jù)還沒(méi)過(guò)來(lái),線程B則進(jìn)入等待狀態(tài),當(dāng)線程A的任務(wù)處理完成,則通知線程B去容器中獲取數(shù)據(jù),這樣基于線程等待和通知的機(jī)制來(lái)協(xié)作完成任務(wù)。

3、基礎(chǔ)方法

等待/通知機(jī)制的相關(guān)方法是Java中Object層級(jí)的基礎(chǔ)方法,任何對(duì)象都有該方法:

  • notify:隨機(jī)通知一個(gè)在該對(duì)象上等待的線程,使其結(jié)束wait狀態(tài)返回;
  • notifyAll:?jiǎn)拘言谠搶?duì)象上所有等待的線程,進(jìn)入對(duì)象鎖爭(zhēng)搶隊(duì)列中;
  • wait:線程進(jìn)入waiting等待狀態(tài),不會(huì)爭(zhēng)搶鎖對(duì)象,也可以設(shè)置等待時(shí)間;

線程的等待通知機(jī)制,就是基于這幾個(gè)基礎(chǔ)方法。

二、等待通知原理

1、基本原理

等待/通知機(jī)制,該模式下指線程A在不滿足任務(wù)執(zhí)行的情況下調(diào)用對(duì)象wait()方法進(jìn)入等待狀態(tài),線程B修改了線程A的執(zhí)行條件,并調(diào)用對(duì)象notify()或者notifyAll()方法,線程A收到通知后從wait狀態(tài)返回,進(jìn)而執(zhí)行后續(xù)操作。兩個(gè)線程通過(guò)基于對(duì)象提供的wait()/notify()/notifyAll()等方法完成等待和通知間交互,提高程序的可伸縮性。

2、實(shí)現(xiàn)案例

通過(guò)線程通信解決上述數(shù)據(jù)生成和存儲(chǔ)任務(wù)的解耦流程。

public class NotifyThread01 {

    static Object lock = new Object() ;
    static volatile List<String> dataList = new ArrayList<>();

    public static void main(String[] args) throws Exception {
        Thread saveThread = new Thread(new SaveData(),"SaveData");
        saveThread.start();
        TimeUnit.SECONDS.sleep(3);
        Thread dataThread = new Thread(new AnalyData(),"AnalyData");
        dataThread.start();
    }
    // 等待數(shù)據(jù)生成,保存
    static class SaveData implements Runnable {
        @Override
        public void run() {
            synchronized (lock){
                while (dataList.size()==0){
                    try {
                        System.out.println(Thread.currentThread().getName()+"等待...");
                        lock.wait();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
                System.out.println("SaveData .."+ dataList.get(0)+dataList.get(1));
            }
        }
    }
    // 生成數(shù)據(jù),通知保存
    static class AnalyData implements Runnable {
        @Override
        public void run() {
            synchronized (lock){
                dataList.add("hello,");
                dataList.add("java");
                lock.notify();
                System.out.println("AnalyData End...");
            }
        }
    }
}

注意:除了dataList滿足寫(xiě)條件,還要在AnalyData線程執(zhí)行通知操作。

三、管道流通信

1、管道流簡(jiǎn)介

基本概念

管道流主要用于在不同線程間直接傳送數(shù)據(jù),一個(gè)線程發(fā)送數(shù)據(jù)到輸出管道,另一個(gè)線程從輸入管道中讀取數(shù)據(jù),進(jìn)而實(shí)現(xiàn)不同線程間的通信。

實(shí)現(xiàn)分類(lèi)

管道字節(jié)流:PipedInputStream和PipedOutputStream;

管道字符流:PipedWriter和PipedReader;

新IO管道流:Pipe.SinkChannel和Pipe.SourceChannel;

2、使用案例

public class NotifyThread02 {
    public static void main(String[] args) throws Exception {
        PipedInputStream pis = new PipedInputStream();
        PipedOutputStream pos = new PipedOutputStream();
        // 鏈接輸入流和輸出流
        pos.connect(pis);
        // 寫(xiě)數(shù)據(jù)線程
        new Thread(new Runnable() {
            public void run() {
                BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
                // 將從鍵盤(pán)讀取的數(shù)據(jù)寫(xiě)入管道流
                PrintStream ps = new PrintStream(pos);
                while (true) {
                    try {
                        System.out.print(Thread.currentThread().getName());
                        ps.println(br.readLine());
                        Thread.sleep(1000);
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }
            }
        }, "輸入數(shù)據(jù)線程:").start();
        // 讀數(shù)據(jù)線程
        new Thread(new Runnable() {
            public void run() {
                BufferedReader br = new BufferedReader(new InputStreamReader(pis));
                while (true) {
                    try {
                        System.out.println(Thread.currentThread().getName() + br.readLine());
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
            }
        }, "輸出數(shù)據(jù)線程:").start();
    }
}

寫(xiě)線程向管道流寫(xiě)入數(shù)據(jù),讀線程讀取數(shù)據(jù),完成基本通信流程。

四、生產(chǎn)消費(fèi)模式

1、業(yè)務(wù)場(chǎng)景

基于線程等待通知機(jī)制:實(shí)現(xiàn)工廠生產(chǎn)一件商品,通知商店賣(mài)出一件商品的業(yè)務(wù)流程。

2、代碼實(shí)現(xiàn)

public class NotifyThread03 {
    public static void main(String[] args) {
        Product product = new Product();
        ProductFactory productFactory = new ProductFactory(product);
        ProductShop productShop = new ProductShop(product);
        productFactory.start();
        productShop.start();
    }
}
// 產(chǎn)品
class Product {
    public String name ;
    public double price ;
    // 產(chǎn)品是否生產(chǎn)完畢,默認(rèn)沒(méi)有
    boolean flag ;
}
// 產(chǎn)品工廠:生產(chǎn)
class ProductFactory extends Thread {
    Product product ;
    public ProductFactory (Product product){
        this.product = product;
    }
    @Override
    public void run() {
        int i = 0 ;
        while (i < 20) {
            synchronized (product) {
                if (!product.flag){
                    if (i%2 == 0){
                        product.name = "鼠標(biāo)";
                        product.price = 79.99;
                    } else {
                        product.name = "鍵盤(pán)";
                        product.price = 89.99;
                    }
                    System.out.println("產(chǎn)品:"+product.name+"【價(jià)格:"+product.price+"】出廠...");
                    product.flag = true ;
                    i++;
                    // 通知消費(fèi)者
                    product.notifyAll();
                } else {
                    try {
                        // 進(jìn)入等待狀態(tài)
                        product.wait();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
        }
    }
}
// 產(chǎn)品商店:銷(xiāo)售
class ProductShop extends Thread {
    Product product ;
    public ProductShop (Product product){
        this.product = product ;
    }
    @Override
    public void run() {
        while (true) {
            synchronized (product) {
                if (product.flag == true ){
                    System.out.println("產(chǎn)品:"+product.name+"【價(jià)格"+(product.price*2)+"】賣(mài)出...");
                    product.flag = false ;
                    product.notifyAll(); //喚醒生產(chǎn)者
                } else {
                    try {
                        product.wait();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
        }
    }
}

流程描述:ProductFactory生成一件商品,通知商店售賣(mài),通過(guò)flag標(biāo)識(shí)判斷控制是否進(jìn)入等待狀態(tài),商店賣(mài)出商品后,再次通知工廠生產(chǎn)商品。

五、源代碼地址

GitHub·地址
https://github.com/cicadasmile/java-base-parent
GitEE·地址
https://gitee.com/cicadasmile/java-base-parent

以上就是Java并發(fā)編程之線程間的通信的詳細(xì)內(nèi)容,更多關(guān)于Java 線程間通信的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • 如何基于springboot-admin實(shí)現(xiàn)后臺(tái)監(jiān)控

    如何基于springboot-admin實(shí)現(xiàn)后臺(tái)監(jiān)控

    這篇文章主要介紹了如何基于springboot-admin實(shí)現(xiàn)后臺(tái)監(jiān)控,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2020-04-04
  • Java圖片批量壓縮像素的實(shí)現(xiàn)方法

    Java圖片批量壓縮像素的實(shí)現(xiàn)方法

    我們開(kāi)發(fā)中經(jīng)常會(huì)遇到原圖清晰度高,考慮到效率問(wèn)題,我們不可能拿原圖進(jìn)行顯示,服務(wù)端一般都要對(duì)圖片進(jìn)行壓縮處理,然后發(fā)送給客戶端顯示,這篇文章主要給大家介紹了關(guān)于Java圖片批量壓縮像素的實(shí)現(xiàn)方法,需要的朋友可以參考下
    2021-12-12
  • Java后臺(tái)與微信小程序的數(shù)據(jù)交互實(shí)現(xiàn)

    Java后臺(tái)與微信小程序的數(shù)據(jù)交互實(shí)現(xiàn)

    這篇文章主要介紹了Java后臺(tái)與微信小程序的數(shù)據(jù)交互實(shí)現(xiàn),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2020-12-12
  • java?HttpURLConnection類(lèi)的disconnect方法與http長(zhǎng)連接詳解

    java?HttpURLConnection類(lèi)的disconnect方法與http長(zhǎng)連接詳解

    這篇文章主要介紹了java?HttpURLConnection類(lèi)的disconnect方法與http長(zhǎng)連接,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2024-04-04
  • 線程安全的單例模式的幾種實(shí)現(xiàn)方法分享

    線程安全的單例模式的幾種實(shí)現(xiàn)方法分享

    線程安全的單例模式實(shí)現(xiàn)有幾種思路,個(gè)人認(rèn)為第2種方案最優(yōu)雅:、餓漢式、借助內(nèi)部類(lèi)、普通加鎖解決、雙重檢測(cè),但要注意寫(xiě)法,如果單體模式繼續(xù)擴(kuò)展為N元單體模式,那就是對(duì)象池模式了
    2014-02-02
  • springMVC4之強(qiáng)大類(lèi)型轉(zhuǎn)換器實(shí)例解析

    springMVC4之強(qiáng)大類(lèi)型轉(zhuǎn)換器實(shí)例解析

    本篇文章主要介紹了springMVC4之強(qiáng)大類(lèi)型轉(zhuǎn)換器實(shí)例解析,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2017-04-04
  • java  Iterator接口和LIstIterator接口分析

    java Iterator接口和LIstIterator接口分析

    這篇文章主要介紹了java Iterator接口和LIstIterator接口分析的相關(guān)資料,需要的朋友可以參考下
    2017-05-05
  • JAVA操作HDFS案例的簡(jiǎn)單實(shí)現(xiàn)

    JAVA操作HDFS案例的簡(jiǎn)單實(shí)現(xiàn)

    本篇文章主要介紹了JAVA操作HDFS案例的簡(jiǎn)單實(shí)現(xiàn),小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧
    2017-08-08
  • 解析JavaSE的繼承和多態(tài)

    解析JavaSE的繼承和多態(tài)

    這篇文章主要為大家詳細(xì)介紹了JavaSE的繼承和多態(tài),文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下,希望能夠給你帶來(lái)幫助
    2022-03-03
  • WIN10系統(tǒng)中添加bat腳本重啟jar服務(wù)

    WIN10系統(tǒng)中添加bat腳本重啟jar服務(wù)

    在bat腳本中執(zhí)行java服務(wù),命令與cmd中類(lèi)似,下面這篇文章主要給大家介紹了關(guān)于WIN10系統(tǒng)中添加bat腳本重啟jar服務(wù)的相關(guān)資料,文中通過(guò)圖文介紹的非常詳細(xì),需要的朋友可以參考下
    2023-12-12

最新評(píng)論

延寿县| 商河县| 龙里县| 特克斯县| 山东省| 博罗县| 洮南市| 荆州市| 田林县| 赤壁市| 临沭县| 平舆县| 蕲春县| 遂昌县| 五大连池市| 长沙市| 潜山县| 松溪县| 太湖县| 襄垣县| 湾仔区| 武功县| 雷波县| 黔江区| 张家界市| 伊金霍洛旗| 容城县| 吐鲁番市| 阜康市| 湘阴县| 卢龙县| 县级市| 忻城县| 阳高县| 镇赉县| 衡阳市| 正宁县| 长岭县| 西林县| 庆城县| 乌拉特前旗|