溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

java中生產者和消費者問題實例分析

發(fā)布時間:2022-02-08 15:08:51 來源:億速云 閱讀:147 作者:iii 欄目:開發(fā)技術

這篇“java中生產者和消費者問題實例分析”文章的知識點大部分人都不太理解,所以小編給大家總結了以下內容,內容詳細,步驟清晰,具有一定的借鑒價值,希望大家閱讀完這篇文章能有所收獲,下面我們一起來看看這篇“java中生產者和消費者問題實例分析”文章吧。

    應用場景

    假設倉庫中只能存放一件產品,生產者將生產出來的產品放入倉庫,消費者將倉庫中產品取走消費

    如果倉庫中沒有產品,則生產者將產品放入倉庫,否則停止生產并等待,直到倉庫中的產品被消費者取走為止

    如果倉庫中放有產品,則消費者可以將產品取走消費,否則停止消費并等待,直到倉庫中再次放入產品為止

    分析

    這是一個線程同步問題,生產者和消費者共享同一個資源,并且生產者和消費者之間相互依賴,互為條件。

    對于生產者,沒有生產產品之前,要通知消費者等待,而生產了產品之后,又需要馬上通知消費者消費

    對于消費者,在消費之后,要通知生產者已經結束消費,需要生產新的產品以供消費

    在生產者消費者問題中,僅有synchronized是不夠的

    synchronized可阻止并發(fā)更新同一個共享資源,實現了同步

    synchronized不能用來實現不同線程之間的消息傳遞(通信)

    Java提供了幾個方法解決線程之間的通信問題

    方法名作用
    wait()表示線程一直等待,直到其他線程通知,與sleep不同,wait()會釋放鎖
    wait(long timeout)指定等待的毫秒數
    notify()喚醒一個處于等待狀態(tài)的線程
    notifyAll()喚醒同一個對象上所有調用wait()方法的線程,優(yōu)先級別高的線程優(yōu)先調度

    注意:均是Object類的方法,都只能在同步方法或者同步代碼塊中使用,否則會拋出異常

    解決方法

    管程法

    生產者:負責生產數據的模塊(可能是方法、對象、線程、進程)

    消費者:負責處理數據的模塊(可能是方法、對象、線程、進程)

    緩沖區(qū):消費者不能直接使用生產者的數據,他們之間有個“緩沖區(qū)”

    生產者將生產好的數據放入緩沖區(qū),消費者從緩沖區(qū)拿出數據

    代碼案例

    //使用緩沖區(qū)解決生產者消費者模型
    public class TestPC {
        public static void main(String[] args) {
            SynContainer container = new SynContainer();
            new Producer(container).start();
            new Consumer(container).start();
        }
    }
    
    class Producer extends Thread{
        SynContainer synContainer;
        public Producer(SynContainer synContainer){
            this.synContainer = synContainer;
        }
        //  生產
        @Override
        public void run() {
            for (int i = 0; i < 100; i++) {
                synContainer.push(new Chicken(i));
                System.out.println("生產了"+i+"只雞");
            }
        }
    }
    
    class Consumer extends Thread{
        SynContainer synContainer;
        public Consumer(SynContainer synContainer){
            this.synContainer = synContainer;
        }
        //  消費
        @Override
        public void run() {
            for (int i = 0; i < 100; i++) {
                System.out.println("消費了-->"+synContainer.pop().id+"只雞");
            }
        }
    }
    
    //產品
    class Chicken{
        int id;
        public Chicken(int id) {
            this.id = id;
        }
    }
    
    //緩沖區(qū)
    class SynContainer{
        Chicken[] chickens = new Chicken[10];
        int count = 0;
        //生產者放入產品
        public synchronized void push(Chicken chicken){
            //如果容器滿了就要等到消費者消費
            if (count==chickens.length){
                try {
                    this.wait();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                //通知消費者消費,自身進入等待
            }
            //沒有滿的話則生產
            chickens[count] = chicken;
            count++;
            //通知消費者消費
            this.notifyAll();
        }
    
        //生產者消費產品
        public synchronized Chicken pop(){
            if (count==0){
                //等待生產者生產
                try {
                    this.wait();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            count--;
            Chicken chicken = chickens[count];
            //消費了,可以通知生產者繼續(xù)生產
            this.notifyAll();
            return chicken;
        }
    }

    信號燈法

    通過標志位 true 或者 false 來進行判斷

    代碼案例

    //信號燈法測試生產者消費者模型 即標志位
    public class TestPC2 {
        public static void main(String[] args) {
            TV tv = new TV();
            new Player(tv).start();
            new Audiance(tv).start();
        }
    
    }
    
    //生產者-->演員
    class Player extends Thread {
        TV tv;
        public Player(TV tv){
            this.tv = tv;
        }
    
        @Override
        public void run() {
            for (int i = 0; i < 20; i++) {
                if (i%2==0){
                    this.tv.play("天天向上");
                }else {
                    this.tv.play("抖音廣告");
                }
            }
        }
    }
    
    //消費者-->觀眾
    class  Audiance extends Thread{
        TV tv;
        public Audiance(TV tv){
            this.tv = tv;
        }
    
        @Override
        public void run() {
            for (int i = 0; i < 20; i++) {
                tv.watch();
            }
        }
    }
    
    //產品-->節(jié)目
    class TV{
        //演員表演 觀眾等待 T
        //觀眾觀看 演員等待 F
        String show;//表演的節(jié)目
        boolean flag = true;
    
        //表演
        public synchronized void play(String show){
            if (!flag){
                try {
                    this.wait();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            System.out.println("演員表演了:"+show);
            //通知觀眾
            this.notifyAll();
            this.show = show;
            this.flag = !this.flag;
        }
    
        //觀看
        public synchronized void watch(){
            if (flag){
                try {
                    this.wait();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            System.out.println("觀看了"+show);
            //通知演員表演
            this.notifyAll();
            this.flag = !this.flag;
        }
    }

    以上就是關于“java中生產者和消費者問題實例分析”這篇文章的內容,相信大家都有了一定的了解,希望小編分享的內容對大家有幫助,若想了解更多相關的知識內容,請關注億速云行業(yè)資訊頻道。

    向AI問一下細節(jié)

    免責聲明:本站發(fā)布的內容(圖片、視頻和文字)以原創(chuàng)、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

    AI