1,从名字上看,就是多线程教程中最普遍的消费与生产问题。
2.适用范围,由于消费和生产分别由不同的线程来进行,这里就有一个速度同步的问题,有可能消费线程运行比较快,产品还没有被生产出来,也有可能消费线程运行比较慢,产品造成了积压,Producer-Consumer就是要解决消费线程与生产线程的同步问题。
3,实现方式,这里有3个概念,Producer生产者,负责生产产品,这里的产品可以是普通的数据,一个简单的实例对象等。Consumer消费者,负责消费生产者生产出来的产品。Channel通道,主要用于存放产品的地方,并且把产品提供给消费者消费,通道就是为了协调消费者与生产者之间的速度差,确保不会出现生产者与消费者不同步的情况发生。对于消费者和生产者,通道都会先检查保护条件,如果不满足保护条件就会让当前线程进入等待,如果满足就会执行操作,并且通知对方正在等待的线程。主要使用wait和notifyAll方法
4.代码实现
1)定义channer类,分别定义消费者使用的消费方法和生产者使用的生产方法,具体见代码注解
package producerconsumer.study;
import java.util.LinkedList;
public class Channel {
private LinkedList<String> products=new LinkedList<String>();
public synchronized void produce() throws InterruptedException {
while(products.size()>=2) //最多只生产2个产品,超过2个表示还没有被消费,生产线程需要等待
{
System.out.println("Too many product, producer wait consumer to consum");
wait();
}
products.add("product1"); //生产产品
products.add("product2"); //生产产品
System.out.println("produce product");
notifyAll(); //生产完了通知消费线程消费产品
}
public synchronized void consum() throws InterruptedException {
while(products.size()==0) //没有产品可供消费,消费线程需要等待
{
System.out.println("no product, consumer wait producer to produce");
wait();
}
while(products.size()>0) { //消费产品
String product = products.pollFirst();
System.out.println("consum product:"+product);
}
notifyAll(); //消费完了,通知等待的生产线程继续生产产品
}
}
2) 分别启动消费线程和生产线程,分别调用通道类的消费方法和生产方法,各调用10次
package producerconsumer.study;
import java.util.Random;
public class ProducerConsumer {
public static void main(String[] args) {
Channel channel=new Channel();
Thread producer=new Thread(
new Runnable() {
@Override
public void run() {
Random random=new Random(5);
for(int i=0;i<10;i++) {
try {
channel.produce();
Thread.sleep(random.nextInt(100));//随机降低线程执行速度
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
);
Thread consumer=new Thread(
new Runnable() {
@Override
public void run() {
Random random=new Random(4);
for(int i=0;i<10;i++) {
try {
channel.consum();
Thread.sleep(random.nextInt(100)); //随机降低线程执行速度
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
);
producer.start();
consumer.start();
}
}
3) 运行结果
//第一次调用结果
produce product
consum product:product1
consum product:product2
//第二次调用
no product, consumer wait producer to produce //消费完了,没有产品,消费线程进入等待
produce product //生产线程生产了产品,通知消费线程
consum product:product1 //消费线程消费产品1
consum product:product2 //消费线程消费产品1
no product, consumer wait producer to produce
produce product
consum product:product1
consum product:product2
no product, consumer wait producer to produce
produce product
consum product:product1
consum product:product2
produce product
Too many product, producer wait consumer to consum
consum product:product1
consum product:product2
produce product //生产完了2个产品
Too many product, producer wait consumer to consum //此时开始下一次调用,由于还没有被消费完,生产线程等待
consum product:product1 //消费产品1
consum product:product2 //消费产品2,消费完了,通知生产线程继续下一次的生产
produce product //下一次生产完成
consum product:product1
consum product:product2
no product, consumer wait producer to produce
produce product
consum product:product1
consum product:product2
no product, consumer wait producer to produce
produce product
consum product:product1
consum product:product2
produce product
consum product:product1
consum product:product2