生產者消費者模型
- 生產者線程:能夠生產兩種產品(中文、英文),生產者產出信息後將其放到一個區域之中;
- 消費者線程:不停的從區域中取走生產者生產出來的產品;
- 產品的生產是需要耗費一定時間的。
基本實現
- 定義一個產品類Product,作爲產品存放區;
- 定義Productor線程,生產產品;
- 定義Consumer線程,取走產品。
//產品
class Product {
private String name = "蘋果";
private String content = "愛瘋";
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getContent() {
return content;
}
public void setContent(String content) {
this.content = content;
}
}
//生產者線程
class Productor implements Runnable {
private Product product = null;
public Productor(Product product){
this.product = product;
}
public void run() {
boolean flag = true; //控制生產哪種產品
for(int i = 0; i < 50; i++) {
if(flag) { //如果flag是TRUE,生產第一種產品
this.product.setName("蘋果");
try { //線程休眠,模擬生產需要時間
Thread.sleep(90);
} catch (Exception e) {
e.printStackTrace();
}
this.product.setContent("愛瘋");
flag = false;
} else {
this.product.setName("Apple");
try {
Thread.sleep(90);
} catch (Exception e) {
e.printStackTrace();
}
this.product.setContent("Iphone");
flag = true;
}
}
}
}
//消費者線程
class Consumer implements Runnable {
private Product product = null;
public Consumer(Product product) {
this.product = product;
}
public void run() {
for(int i = 0; i < 50; i++) {
try {
Thread.sleep(100);
} catch (Exception e) {
e.printStackTrace();
}
System.out.println(this.product.getName() + " ----> " + this.product.getContent()); //取走產品
}
}
}
//MAIN函數
public class ProductorConsumerDemo {
public static void main(String[] args) {
Product product = new Product(); //產品存放區
Productor productor = new Productor(product);
Consumer consumer = new Consumer(product);
new Thread(productor).start(); //啓動生產者線程,生產產品
new Thread(consumer).start(); //啓動消費者線程,取走產品
}
}
運行結果:
Apple ----> 愛瘋
蘋果 ----> Iphone
Apple ----> 愛瘋
蘋果 ----> 愛瘋
Apple ----> Iphone
Apple ----> Iphone
Apple ----> Iphone
Apple ----> Iphone
Apple ----> Iphone
Apple ----> Iphone
存在的問題
- 中文產品與英文產品的信息混在一起:原因是因爲生產需要一定的時間,當生產者線程中一種產品還沒生產完就切換到消費者線程,解決方案是生產者線程在生產的時候需要加入同步操作;
- 生產者生產了若干個產品,消費者纔開始取走產品:原因是生產者線程在休眠的時候,消費者線程重複取走產品,解決方案是加入等待喚醒機制。
問題的解決
- 將Product類生產和讀取封裝成不同的方法,並將其設置爲同步方法;
- 在生產和消費方法中加入等待喚醒機制,生產方法需要等待消費方法取走產品後的通知才能繼續生產,消費方法需要等待生產方法生產完成通知後才能繼續取走。
代碼實現:
//產品
class Product {
private String name = "蘋果";
private String content = "愛瘋";
private boolean flag = false; //是否可取走產品的標誌位,TRUE可取走,FALSE可生產
//封裝生產方法
public synchronized void set(String name, String content) { //同步方法解決問題一
if(!flag) {
try {
super.wait(); //生產者線程等待,線程等待喚醒解決問題二
} catch (Exception e) {
e.printStackTrace();
}
}
this.setName(name);
try {
Thread.sleep(300);
} catch (Exception e) {
e.printStackTrace();
}
this.setContent(content);
flag = false;
super.notify(); //喚醒消費者線程
}
//封裝消費方法
public synchronized void get() {
if(flag) {
try {
super.wait();
} catch (Exception e) {
e.printStackTrace();
}
}
try {
Thread.sleep(300);
} catch (Exception e) {
e.printStackTrace();
}
System.out.println(this.getName() + " ----> " + this.getContent()); //取走產品
flag = true;
super.notify();
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getContent() {
return content;
}
public void setContent(String content) {
this.content = content;
}
}
//生產者線程
class Productor implements Runnable {
private Product product = null;
public Productor(Product product){
this.product = product;
}
public void run() {
boolean flag = true; //控制生產哪種產品
for(int i = 0; i < 50; i++) {
if(flag) { //如果flag是TRUE,生產第一種產品
this.product.set("蘋果", "愛瘋");
flag = false;
} else {
this.product.set("Apple", "Iphone");
flag = true;
}
}
}
}
//消費者線程
class Consumer implements Runnable {
private Product product = null;
public Consumer(Product product) {
this.product = product;
}
public void run() {
for(int i = 0; i < 50; i++) {
try {
Thread.sleep(100);
} catch (Exception e) {
e.printStackTrace();
}
this.product.get();
}
}
}
//MAIN函數
public class ProductorConsumerDemo {
public static void main(String[] args) {
Product product = new Product(); //產品存放區
Productor productor = new Productor(product);
Consumer consumer = new Consumer(product);
new Thread(productor).start(); //啓動生產者線程,生產產品
new Thread(consumer).start(); //啓動消費者線程,取走產品
}
}
BR~
Jianwei Wang