生产者、消费者问题
生产者(Productor)将产品交给店员(Clerk),而消费者(Customer)从店员处取走产品,店员一次只能持有固定数量的产品(比如:20),如果生产者试图生产更多的产品,店员会叫生产者停一下,如果店中有空位放产品了再通知生产者继续生产;如果店中没有产品了,店员会告诉消费者等一下,如果店中有产品了再通知消费者来取走产品。
这里可能出现两个问题:
生产者比消费者快时,消费者会漏掉一些数据没有取到。
消费者比生产者快时,消费者会取相同的数据。
三种角色
三种角色:生产者、消费者、产品
两种关系:生产者与生产者之间是互斥关系,消费者与消费者之间是互斥关系,生产者与消费者之间是同步与互斥关系。
一个共享资源:产品
代码实现
wait() / notify()方法
当缓冲区已满时,生产者线程停止执行,放弃锁,使自己处于等状态,让其他线程执行;
当缓冲区已空时,消费者线程停止执行,放弃锁,使自己处于等状态,让其他线程执行。
当生产者向缓冲区放入一个产品时,向其他等待的线程发出可执行的通知,同时放弃锁,使自己处于等待状态;
当消费者从缓冲区取出一个产品时,向其他等待的线程发出可执行的通知,同时放弃锁,使自己处于等待状态。
package com.jd.java;
/**
* 在该问题中,为了演示效果,我们选用两个消费者,一个生产者来实现
* @author wds
* @date 2021-11-16-22:43
*/
public class ProducerTest {
public static void main(String[] args) {
Product product = new Product();
Producer producer = new Producer(product);
Consumer consumer = new Consumer(product);
Consumer consumer1 = new Consumer(product);
producer.setName("生产者1");
consumer.setName("消费者1");
consumer1.setName("消费者2");
producer.start();
consumer.start();
consumer1.start();
}
}
class Product { //产品
private static int proCount = 0;
public synchronized void producerProduct() {
if(proCount<20){
try {
Thread.sleep(20);
} catch (InterruptedException e) {
e.printStackTrace();
}
proCount++;
System.out.println(Thread.currentThread().getName()+":开始生产第"+proCount+"个产品.");
notify(); //唤醒被wait()的生产者
}else{
try {
wait(); //等待
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
public synchronized void consumerProduct() {
if(proCount>0){
try {
Thread.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName()+":开始消费第"+proCount+"个产品.");
proCount--;
notify(); //唤醒被wait()的生产者线程
}else{
try {
wait(); //等待
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
class Producer extends Thread{ //生产者
private Product product;
public Producer(Product product){
this.product = product;
}
@Override
public void run() {
System.out.println(Thread.currentThread().getName()+"开始生产产品...");
while(true){
product.producerProduct();
}
}
}
class Consumer extends Thread{ //消费者
private Product product;
public Consumer(Product product){
this.product = product;
}
@Override
public void run() {
System.out.println(Thread.currentThread().getName()+"开始消费产品...");
while(true){
product.consumerProduct();
}
}
}
实现效果: