1. 程式人生 > >Java生產者消費者模型

Java生產者消費者模型

文章目錄

什麼是生產者消費者模型

生產者消費者模式是通過一個容器來解決生產者和消費者的強耦合問題。生產者和消費者彼此之
間不直接通訊,而通過阻塞佇列來進行通訊,所以生產者生產完資料之後不用等待消費者處理,
直接扔給阻塞佇列,消費者不找生產者要資料,而是直接從阻塞佇列裡取,阻塞佇列就相當於一
個緩衝區,平衡了生產者和消費者的處理能力。

這個阻塞佇列就是用來給生產者和消費者解耦的。縱觀大多數設計模式,都會找一個第三者出來進行
解耦,如工廠模式的第三者是工廠類,模板模式的第三者是模板類。在學習一些設計模式的過程中,
如果先找到這個模式的第三者,能幫助我們快速熟悉一個設計模式。

模型程式碼

    package com.donews.frame.sdk;

import java.util.ArrayList;
import java.util.List;
import java.util.Random;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

/**
 * Created by 79653 on 2018/10/22.
 * 描述:
 */
public class JavaActivity {
    public static void main(String[] args) {
    	//資料緩衝區,用來解耦
        List<RunnableData> mQuene=new ArrayList<>();
        Producter producter=new Producter(mQuene);
        Producter producter1=new Producter(mQuene);
        Producter producter2=new Producter(mQuene);
        Producter producter3=new Producter(mQuene);
        Producter producter4=new Producter(mQuene);
        Consumer consumer=new Consumer(mQuene);
        Consumer consumer1=new Consumer(mQuene);
        Consumer consumer2=new Consumer(mQuene);
        Consumer consumer3=new Consumer(mQuene);
        Consumer consumer4=new Consumer(mQuene);
        ExecutorService service=Executors.newCachedThreadPool();
        service.execute(producter);
        service.execute(producter1);
        service.execute(producter2);
        service.execute(producter3);
        service.execute(producter4);
        service.execute(consumer);
        service.execute(consumer1);
        service.execute(consumer2);
        service.execute(consumer3);
        service.execute(consumer4);
    }

   static class RunnableData {
        public int data;

        public RunnableData(int data) {
            this.data = data;
        }
    }

  static   class Producter implements Runnable {
        List<RunnableData> mDataList;
        Random mRandom = new Random();

        public Producter(List<RunnableData> data) {
            mDataList = data;
        }

        @Override
        public void run() {
            try {
                while (true) {
                    if (Thread.currentThread().isInterrupted()) {
                        return;
                    }
                    synchronized (mDataList) {
                        if (mDataList != null && mDataList.size() > 10) {
                        //喚醒其他執行緒,同時自己進入等待狀態
                            mDataList.notifyAll();
                            mDataList.wait();
                        } else {
                            RunnableData data = new RunnableData(mRandom.nextInt());
                            mDataList.add(data);
                            System.out.println("生產者生產了一個數據---------" + data.data);
                        }
                    }
                    Thread.sleep(1000);
                }
            } catch (InterruptedException e) {
                e.printStackTrace();
//                Thread.currentThread().isInterrupted();
            }
        }
    }

  static   class Consumer implements Runnable {
        List<RunnableData> mDataList;

        public Consumer(List<RunnableData> data) {
            mDataList = data;
        }

        @Override
        public void run() {
            try {
                while (true) {
                    if (Thread.currentThread().isInterrupted()) {
                        return;
                    }
                    synchronized (mDataList) {
                        if (mDataList == null || mDataList.size() == 0) {
                            mDataList.notifyAll();
                            mDataList.wait();
                        }
                        RunnableData data = mDataList.remove(0);
                        System.out.println("消費者消費了一條資料---" + data.data);
                    }
                    Thread.sleep(1000);
                }
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}

實際應用例項

  • 最近公司的專案設計到廣告這一層面,我們想在廣告使用時有一個池子會一直有廣告,然後需要的 時候我們就會從這個池子裡面去取,這和我們的模型一模一樣,程式碼幾乎也一樣,只是生產者和消費者乾的是行情不一樣