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

Java多線程:生產(chǎn)者與消費(fèi)者案例

 更新時(shí)間:2021年07月27日 17:06:56   作者:魚小洲  
這篇文章主要介紹了Java并發(fā)編程中的生產(chǎn)者與消費(fèi)者模型簡述,多線程并發(fā)是Java編程中最終要的部分之一,需要的朋友可以參考下,希望能給你帶來幫助

前言

想象一下生活中哪些是和線程沾邊的?飯店炒菜就是一個很好的例子

首先客人要吃菜,前提是廚師要炒好,也就是說,廚師不炒好的話客人是沒有飯菜的。這時(shí)候,廚師就是一個線程,客人拿菜就是另一個線程。

工具

jdk13,IDEA2019.1.4

知識點(diǎn)

Thread、Runnable、synchronized、面向?qū)ο笾R(繼承、封裝、接口、方法重寫)、條件判斷以及線程的一些其他知識點(diǎn)

設(shè)計(jì)思路

首先要有兩個線程,也就是說要兩個類,分別是Producer(生產(chǎn)者)和Consumer(消費(fèi)者)。

由于我們是模擬廚師與客人之間的互動,也就是說還需要一個類來封裝信息:Message(類)。

然后,避免線程之間發(fā)生數(shù)據(jù)混亂的情況,肯定還需要使用synchronized來進(jìn)行線程同步。

具體步驟

首先我們來一份沒有用synchronized的代碼,先看看效果:

public class Message {
    private String title;
    private String content;
    Message(){
    };
    public Message(String title, String content) {
        this.title = title;
        this.content = content;
    }
    public String getTitle() {
        return title;
    }
    public void setTitle(String title) {
        this.title = title;
    }
    public String getContent() {
        return content;
    }
    public void setContent(String content) {
        this.content = content;
    }
}
/*
* 定義生產(chǎn)者類Producer
* */
class Producer implements Runnable{
    private Message msg=null;
    public Producer(Message msg) {
        this.msg = msg;
    }
    @Override
    public void run() {
        for (int i=0;i<=50;i++){
            if (i%2==0){
                this.msg.setTitle("喜歡夜雨嗎?");
                try {
                    Thread.sleep(100);
                }catch (InterruptedException e){
                    System.out.println(e);
                }
                this.msg.setContent("是的呢!");
            }else {
                this.msg.setTitle("還不關(guān)注我嗎?");
                try {
                    Thread.sleep(100);
                }catch (InterruptedException e){
                    System.out.println(e);
                }
                this.msg.setContent("好的呢!");
            }
        }
    }
}
/*
* 定義消費(fèi)者類Consumer
* */
class Consumer implements Runnable{
    private Message msg=null;
    public Consumer(Message msg) {
        this.msg = msg;
    }
    @Override
    public void run() {
        for (int i=0;i<=50;i++){
            try {
                Thread.sleep(100);
            }catch (InterruptedException e){
                System.out.println(e);
            }
            System.out.println(this.msg.getTitle()+"--->"+this.msg.getContent());
        }
    }
}
class TestDemo{
    public static void main(String[] args) {
        Message msg=new Message();
        new Thread(new Producer(msg)).start();
        new Thread(new Consumer(msg)).start();
    }
}

看看運(yùn)行結(jié)果:

在這里插入圖片描述

看仔細(xì)咯,發(fā)生了數(shù)據(jù)錯亂啊,Title與Content沒有一一對應(yīng)欸。咋辦?

能咋辦,改代碼唄。

發(fā)生數(shù)據(jù)混亂的原因完全是因?yàn)?,生產(chǎn)者線程還沒生產(chǎn)的時(shí)候,消費(fèi)者就已經(jīng)消費(fèi)了(至于消費(fèi)的啥我也不知道,我也不敢問?。?。所以造成了數(shù)據(jù)混亂,不過我們上面說了啊,要使用synchronized來讓線程同步一下。但是又會出問題,我們接著往下看

class TestDemo{
    public static void main(String[] args) {
        Message msg=new Message();
        new Thread(new Producer(msg)).start();
        new Thread(new Consumer(msg)).start();
    }
}
class Message{
    private String title,content;
    public synchronized void set(String title,String content){
        this.title=title;
        this.content=content;
    }
    public synchronized void get(){
        try {
            Thread.sleep(1000);
        }catch (InterruptedException e){
            System.out.println(e);
        }
        System.out.println(this.title+"-->"+this.content);
    }
    public String getContent() {
        return content;
    }
    public void setContent(String content) {
        this.content = content;
    }
    public String getTitle() {
        return title;
    }
    public void setTitle(String title) {
        this.title = title;
    }
}
class Producer implements Runnable{
    private Message msg=null;
    Producer(Message msg){
        this.msg=msg;
    }
    @Override
    public void run() {
        for (int i=0;i<=50;i++){
            if (i%2==0){
                this.msg.set("喜歡夜雨嗎?","是的呢!");
            }else {
                this.msg.set("還不關(guān)注嗎?","好的呢!");
            }
        }
    }
}
class Consumer implements Runnable{
    private Message msg=null;
    Consumer(Message msg){
        this.msg=msg;
    }
    @Override
    public void run() {
        for (int i=0;i<=50;i++){
            this.msg.get();
        }
    }
}

我又重新封裝了一些方法,然后運(yùn)行的時(shí)候,wc,數(shù)據(jù)倒是不混亂了,但是呢,數(shù)據(jù)重復(fù)了一大堆。

在這里插入圖片描述

為啥會出現(xiàn)這個問題呢?最后想了一下,會出現(xiàn)這種問題的,就是因?yàn)榫€程的執(zhí)行順序的問題。我們想要實(shí)現(xiàn)的效果是生產(chǎn)者線程執(zhí)行了之后,讓生產(chǎn)者線程等待,而后讓消費(fèi)者線程執(zhí)行,等待消費(fèi)者線程執(zhí)行完成之后就又讓生產(chǎn)者線程繼續(xù)執(zhí)行。后來我又查了查官方文檔,發(fā)現(xiàn)Object類中專門有三個方法是與線程相關(guān)的:

方法 描述
public final void wait() throws InterruptedException 線程的等待
public final void notify() 喚醒第一個等待線程
public final void notifyAll()

當(dāng)我看到這些方法的時(shí)候,心里愣了一下,這不就是我們想要的方法嗎,用wait()方法來讓生產(chǎn)者線程等待,然后運(yùn)行消費(fèi)者線程,等消費(fèi)者線程執(zhí)行完了之后又讓生產(chǎn)者線程去執(zhí)行。這其中我們用true和false來表示運(yùn)行開始和運(yùn)行暫停。

最后我們來看看完成品的代碼:

class TestDemo{
    public static void main(String[] args) {
        Message msg=new Message();
        new Thread(new Producer(msg)).start();
        new Thread(new Consumer(msg)).start();
    }
}
class Message extends Exception{
    private String title,content;
    private boolean flag=true;
    // true表示正在生產(chǎn),不要來取走,因?yàn)闆]由讓消費(fèi)者區(qū)走的
    // false表示可以取走,但是不能生產(chǎn)
    public synchronized void set(String title,String content){
        if (this.flag==false){
            try {
                super.wait();
            }catch (InterruptedException e){
                System.out.println(e);
            }
        }
        this.title=title;
        try {
            Thread.sleep(60);
        }catch (InterruptedException e){
            System.out.println(e);
        }
        this.content=content;
        this.flag=true; // 生產(chǎn)完成,修改標(biāo)志位
        super.notify(); // 喚醒等待線程
    }
    public synchronized void get(){
        if (flag==true) {// 已經(jīng)生產(chǎn)好了,等待取走
            try {
                super.wait();
            }catch (InterruptedException e){
                System.out.println(e);
            }
        }
        try {
            Thread.sleep(60);
        }catch (InterruptedException e){
            System.out.println(e);
        }
        System.out.println(this.title+"-->"+this.content);
        this.flag=true;
        super.notify();
    }
    public String getContent() {
        return content;
    }
    public void setContent(String content) {
        this.content = content;
    }
    public String getTitle() {
        return title;
    }
    public void setTitle(String title) {
        this.title = title;
    }
}
class Producer implements Runnable{
    private Message msg=null;
    Producer(Message msg){
        this.msg=msg;
    }
    @Override
    public void run() {
        for (int i=0;i<=50;i++){
            if (i%2==0){
                this.msg.set("喜歡夜雨嗎?","是的呢!");
            }else {
                this.msg.set("還不關(guān)注嗎?","好的呢!");
            }
        }
    }
}
class Consumer implements Runnable{
    private Message msg=null;
    Consumer(Message msg){
        this.msg=msg;
    }
    @Override
    public void run() {
        for (int i=0;i<=50;i++){
            this.msg.get();
        }
    }
}

運(yùn)行結(jié)果我就不貼了,你們自己去測試一下吧…

總結(jié)

這個案例完美的呈現(xiàn)了線程以及面向?qū)ο笾R的綜合運(yùn)用,具有很強(qiáng)的實(shí)際操作性

本篇文章就到這里了,希望能給你帶來幫助,也希望您能夠多多關(guān)注腳本之家的更多內(nèi)容!

相關(guān)文章

  • mybatis模糊查詢、分頁和別名配置的方法

    mybatis模糊查詢、分頁和別名配置的方法

    這篇文章主要介紹了mybatis模糊查詢、分頁和別名配置,本文給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2020-09-09
  • Maven profile實(shí)現(xiàn)不同環(huán)境的配置管理實(shí)踐

    Maven profile實(shí)現(xiàn)不同環(huán)境的配置管理實(shí)踐

    這篇文章主要介紹了Maven profile實(shí)現(xiàn)不同環(huán)境的配置管理實(shí)踐,本文給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2020-09-09
  • 基于spring AOP @Around @Before @After的區(qū)別說明

    基于spring AOP @Around @Before @After的區(qū)別說明

    這篇文章主要介紹了基于spring AOP @Around @Before @After的區(qū)別說明,具有很好的參考價(jià)值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2021-02-02
  • 關(guān)于ZooKeeper原理剖析

    關(guān)于ZooKeeper原理剖析

    ZooKeeper是一種分布式、高可用性的協(xié)調(diào)服務(wù),主要用于幫助系統(tǒng)避免單點(diǎn)故障和建立可靠的應(yīng)用程序,它通過Leader、Follower和Observer的角色來協(xié)調(diào)節(jié)點(diǎn),并提供分布式協(xié)作服務(wù)和維護(hù)配置信息,ZooKeeper在HDFS、YARN、HBase、SmallFS和Kafka等大數(shù)據(jù)產(chǎn)品中都有廣泛的應(yīng)用
    2025-02-02
  • 詳解Java Bellman-Ford算法原理及實(shí)現(xiàn)

    詳解Java Bellman-Ford算法原理及實(shí)現(xiàn)

    Bellman-Ford算法與Dijkstra算法類似,都是以松弛操作作為基礎(chǔ),Bellman-Ford算法是對所有邊都進(jìn)行松弛操作,本文將詳解Bellman-Ford算法原理及實(shí)現(xiàn),感興趣的可以了解一下
    2022-07-07
  • 圖文詳解SpringBoot中Log日志的集成

    圖文詳解SpringBoot中Log日志的集成

    這篇文章主要給大家介紹了關(guān)于SpringBoot中Log日志的集成的相關(guān)資料,文中通過實(shí)例代碼以及圖文介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2021-12-12
  • Java 入門圖形用戶界面設(shè)計(jì)之列表框JList

    Java 入門圖形用戶界面設(shè)計(jì)之列表框JList

    圖形界面(簡稱GUI)是指采用圖形方式顯示的計(jì)算機(jī)操作用戶界面。與早期計(jì)算機(jī)使用的命令行界面相比,圖形界面對于用戶來說在視覺上更易于接受,本篇精講Java語言中關(guān)于圖形用戶界面的列表框JList
    2022-02-02
  • java基礎(chǔ)二叉搜索樹圖文詳解

    java基礎(chǔ)二叉搜索樹圖文詳解

    二叉樹是一種非常重要的數(shù)據(jù)結(jié)構(gòu),它同時(shí)具有數(shù)組和鏈表各自的特點(diǎn),下面這篇文章主要給大家介紹了關(guān)于java基礎(chǔ)二叉搜索樹的相關(guān)資料,文中通過實(shí)例代碼介紹的非常詳細(xì),需要的朋友可以參考下
    2022-03-03
  • Shiro+Redis實(shí)現(xiàn)登錄次數(shù)凍結(jié)的示例

    Shiro+Redis實(shí)現(xiàn)登錄次數(shù)凍結(jié)的示例

    這篇文章主要介紹了Shiro+Redis實(shí)現(xiàn)登錄次數(shù)凍結(jié),文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2020-12-12
  • SpringBoot+Vue實(shí)現(xiàn)數(shù)據(jù)添加功能

    SpringBoot+Vue實(shí)現(xiàn)數(shù)據(jù)添加功能

    這篇文章主要介紹了SpringBoot+Vue實(shí)現(xiàn)數(shù)據(jù)添加功能,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2021-03-03

最新評論

肃南| 迁安市| 资源县| 和平区| 忻州市| 信阳市| 溆浦县| 色达县| 西平县| 霍邱县| 时尚| 江孜县| 盐津县| 哈密市| 碌曲县| 罗平县| 浦北县| 南投市| 酒泉市| 云安县| 河北省| 沛县| 英吉沙县| 浦城县| 淮安市| 茶陵县| 砚山县| 资讯 | 蕲春县| 民权县| 安陆市| 云龙县| 垣曲县| 深水埗区| 彩票| 秦皇岛市| 四会市| 龙门县| 东丰县| 泗洪县| 平罗县|