在线程通信中,有一个非常典型的例子:
生产者消费者模式
一种重要的模型,基于 等待/通知 机制。生产者/消费者 模型描述的是有一块缓冲区作为仓库,生产者可将产品放入仓库,消费者可以从仓库中取出产品,生产者/消费者模型关注的是以下几个点:
- 生产者生产的时候消费者不能消费
- 消费者消费的时候生产者不能生产
- 缓冲区空时消费者不能消费
- 缓冲区满时生产者不能生产
优点:
- 解耦:因为多了一个缓冲区,所以生产者和消费者并不直接相互调用,这一点很容易想到,这样生产者和消费者的代码发生变化,都不会对对方产生影响,这样其实就是使生产者和消费者之间强耦合解开,变成了 生产者和缓冲区 / 消费者和缓冲区 之间的弱耦合。
- 通过平衡生产者和消费者的处理能力来提高整体处理数据的速度,这是生产者/消费者模型最重要的一个优点。如果消费者直接从生产者这里拿数据,如果生产者的速度很慢,但消费者消费的速度很快,那消费者就得占用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();
}
}