前提概要
什麼是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被消費了