java多線程:使用BlockingQueue(阻塞隊列)實現生產者與消費者應用

前提概要

什麼是BlokingQueue

BlockingQueue 是一個先進先出的隊列(Queue),爲什麼說是阻塞(Blocking)的呢?是因爲 BlockingQueue 支持當獲取隊列元素但是隊列爲空時,會阻塞等待隊列中有元素再返回;也支持添加元素時,如果隊列已滿,那麼等到隊列可以放入新元素時再放入。

BlockingQueue 對插入操作、移除操作、獲取元素操作提供了四種不同的方法用於不同的場景中使用:1、拋出異常;2、返回特殊值(null 或 true/false,取決於具體的操作);3、阻塞等待此操作,直到這個操作成功;4、阻塞等待此操作,直到成功或者超時指定時間。


實現代碼

package com.oumuv.producerandconsumer;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.LinkedBlockingDeque;

/**
 * 多線程生產者與消費者問題
 * 生產者生產,消費者立刻消費
 * 使用阻塞隊列 {@link BlockingQueue}保存產品
 */
public class ProducerAndConsumer1 {


    public static void main(String[] args) {
        ProducerAndConsumer1 pac = new ProducerAndConsumer1();
        Storage storage = pac.new Storage();
        Producer p1 = pac.new Producer("生產者1", "小米手機", storage);
        Producer p2 = pac.new Producer("生產者2", "華爲手機", storage);
        Consumer c1 = pac.new Consumer(storage);

        ExecutorService executorService = Executors.newCachedThreadPool();
        executorService.submit(p1);
        executorService.submit(p2);
        executorService.submit(c1);
    }

    /**
     * 生產者
     */
    class Producer implements Runnable {
        private String name;//生產者名稱
        private String pname;//生產的產品
        private Storage storage;

        public Producer(String name, String pname, Storage storage) {
            this.name = name;
            this.pname = pname;
            this.storage = storage;
        }

        @Override
        public void run() {
            try {
                for (int i = 0; i < 15; i++) {
                    Product p = new Product(pname, name);
                    storage.push(p);
                    Thread.sleep(100);
                }
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }

    /**
     * 消費者
     */
    class Consumer implements Runnable {
        private Storage storage;

        public Consumer(Storage storage) {
            this.storage = storage;
        }

        @Override
        public void run() {
            try {
                while (true) {
                    storage.pop();
                    Thread.sleep(500);
                }
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }

    /**
     * 產品信息
     */
    class Product {
        private String name;
        private String from;//來自哪個生產者
        private int id = 0;

        public Product(String name, String from, int id) {
            this.name = name;
            this.from = from;
            this.id = id;
        }

        public Product(String name, String from) {
            this.name = name;
            this.from = from;
        }

        public String getName() {
            return name;
        }

        public String getFrom() {
            return from;
        }

        public int getId() {
            return id;
        }

        public void setId(int id) {
            this.id = id;
        }
    }

    /**
     * 產品倉庫
     */
    class Storage {

        //阻塞隊列
        private BlockingQueue<Product> storage = new LinkedBlockingDeque<>();

        private int index = 1;//用於生成產品編號

        /**
         * 消費
         */
        protected void pop() throws InterruptedException {
            Product product = storage.take();
            System.out.println(product.getFrom() + "的" + product.getName() + "--> id:" + product.getId() + "被消費了");
        }

        /**
         * 生產
         */
        protected void push(Product product) throws InterruptedException {
            storage.put(product);
            product.setId(index++);
            System.out.println(product.getFrom() + ",生產了" + product.getName() + "--> id:" + product.getId());
        }
    }
}


可能輸出的結果

生產者1,生產了小米手機--> id:1
生產者2,生產了華爲手機--> id:2
生產者1的小米手機--> id:1被消費了
生產者1,生產了小米手機--> id:4
生產者2,生產了華爲手機--> id:3
生產者2,生產了華爲手機--> id:5
生產者1,生產了小米手機--> id:6
生產者1,生產了小米手機--> id:7
生產者2,生產了華爲手機--> id:8
生產者2,生產了華爲手機--> id:10
生產者1,生產了小米手機--> id:9
生產者2的華爲手機--> id:2被消費了
生產者1,生產了小米手機--> id:11
生產者2,生產了華爲手機--> id:12
生產者2,生產了華爲手機--> id:14
生產者1,生產了小米手機--> id:13
生產者2,生產了華爲手機--> id:16
生產者1,生產了小米手機--> id:15
生產者2,生產了華爲手機--> id:17
生產者1,生產了小米手機--> id:18
生產者1,生產了小米手機--> id:19
生產者2,生產了華爲手機--> id:20
生產者2的華爲手機--> id:3被消費了
生產者2,生產了華爲手機--> id:21
生產者1,生產了小米手機--> id:22
生產者2,生產了華爲手機--> id:23
生產者1,生產了小米手機--> id:24
生產者2,生產了華爲手機--> id:25
生產者1,生產了小米手機--> id:26
生產者2,生產了華爲手機--> id:27
生產者1,生產了小米手機--> id:28
生產者2,生產了華爲手機--> id:29
生產者1,生產了小米手機--> id:30
生產者1的小米手機--> id:4被消費了
生產者2的華爲手機--> id:5被消費了
生產者1的小米手機--> id:6被消費了
生產者1的小米手機--> id:7被消費了
生產者2的華爲手機--> id:8被消費了
生產者1的小米手機--> id:9被消費了
生產者2的華爲手機--> id:10被消費了
生產者1的小米手機--> id:11被消費了
生產者2的華爲手機--> id:12被消費了
生產者1的小米手機--> id:13被消費了
生產者2的華爲手機--> id:14被消費了
生產者1的小米手機--> id:15被消費了
生產者2的華爲手機--> id:16被消費了
生產者2的華爲手機--> id:17被消費了
生產者1的小米手機--> id:18被消費了
生產者1的小米手機--> id:19被消費了
生產者2的華爲手機--> id:20被消費了
生產者2的華爲手機--> id:21被消費了
生產者1的小米手機--> id:22被消費了
生產者2的華爲手機--> id:23被消費了
生產者1的小米手機--> id:24被消費了
生產者2的華爲手機--> id:25被消費了
生產者1的小米手機--> id:26被消費了
生產者2的華爲手機--> id:27被消費了
生產者1的小米手機--> id:28被消費了
生產者2的華爲手機--> id:29被消費了
生產者1的小米手機--> id:30被消費了
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章