在線程通信中,有一個非常典型的例子:
生產者消費者模式
一種重要的模型,基於 等待/通知 機制。生產者/消費者 模型描述的是有一塊緩衝區作爲倉庫,生產者可將產品放入倉庫,消費者可以從倉庫中取出產品,生產者/消費者模型關注的是以下幾個點:
- 生產者生產的時候消費者不能消費
- 消費者消費的時候生產者不能生產
- 緩衝區空時消費者不能消費
- 緩衝區滿時生產者不能生產
優點:
- 解耦:因爲多了一個緩衝區,所以生產者和消費者並不直接相互調用,這一點很容易想到,這樣生產者和消費者的代碼發生變化,都不會對對方產生影響,這樣其實就是使生產者和消費者之間強耦合解開,變成了 生產者和緩衝區 / 消費者和緩衝區 之間的弱耦合。
- 通過平衡生產者和消費者的處理能力來提高整體處理數據的速度,這是生產者/消費者模型最重要的一個優點。如果消費者直接從生產者這裏拿數據,如果生產者的速度很慢,但消費者消費的速度很快,那消費者就得佔用cpu的時間片等在那邊。
package org.lanqiao.produce_customer.demo;
//生產產品 和消費產品的方式
public class Resouce {
private int pid=0;
/*
* 表示是否已經生產了產品
* true 表示生產了
* false 表示沒有生產
*/
private boolean flag = false;
public synchronized void creat() {
while(true) {
while(flag) {
try {
this.wait();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
try {
Thread.sleep(10);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName()+"生產了一件產品,產品 編號爲" + (++pid));
flag = true;
this.notifyAll();
}
}
public synchronized void destroy() {
while(true) {
while(!flag) {
try {
this.wait();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
try {
Thread.sleep(10);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName()+"消費了編號爲:" +pid +"的產品");
flag = false;
this.notifyAll();
}
}
}
package org.lanqiao.produce_customer.demo;
public class Producer implements Runnable {
private Resouce res ;
public Producer(Resouce res) {
this.res = res;
}
@Override
public void run() {
res.creat();
}
}
package org.lanqiao.produce_customer.demo;
public class Customer extends Thread{
private Resouce res;
public Customer(Resouce res) {
this.res = res;
}
public void run() {
res.destroy();
}
}