Java多线程 生产者消费者模型实例详解

时间:2021-05-20

生产者消费者模型

生产者:生产任务的个体;

消费者:消费任务的个体;

缓冲区:是生产者和消费者之间的媒介,对生产者和消费者解耦。


缓冲区元素为满,生产者无法生产,消费者继续消费;

缓冲区元素为空,消费者无法消费,生产者继续生产;

wait()/notify()生产者消费者模型

制作一个简单的缓冲区ValueObject,value为空表示缓冲区为空,value不为空表示缓冲区满

public class ValueObject { public static String value = "";}

生产者,缓冲区满则wait(),不再生产,等待消费者notify(),缓冲区为空则开始生产

public class Producer { private Object lock; public Producer(Object lock) { this.lock = lock; } public void setValue() { try { synchronized (lock) { if (!ValueObject.value.equals("")) lock.wait(); String value = System.currentTimeMillis() + "_" + System.nanoTime(); System.out.println("Set的值是:" + value); ValueObject.value = value; lock.notify(); } } catch (InterruptedException e) { e.printStackTrace(); } }}

消费者,缓冲区为空则wait(),等待生产者notify(),缓冲区为满,消费者开始消费

public class Customer { private Object lock; public Customer(Object lock) { this.lock = lock; } public void getValue() { try { synchronized (lock) { if (ValueObject.value.equals("")) lock.wait(); System.out.println("Get的值是:" + ValueObject.value); ValueObject.value = ""; lock.notify(); } } catch (InterruptedException e) { e.printStackTrace(); } }}

main方法,启动一个生产者和一个消费者

public class Main { public static void main(String[] args) { Object lock = new Object(); final Producer producer = new Producer(lock); final Customer customer = new Customer(lock); Runnable producerRunnable = new Runnable() { public void run() { while (true) { producer.setValue(); } } }; Runnable customerRunnable = new Runnable() { public void run() { while (true) { customer.getValue(); } } }; Thread producerThread = new Thread(producerRunnable); Thread CustomerThread = new Thread(customerRunnable); producerThread.start(); CustomerThread.start(); }}

运行结果如下

Set的值是:1564733938518_27520480474279Get的值是:1564733938518_27520480474279Set的值是:1564733938518_27520480498378Get的值是:1564733938518_27520480498378Set的值是:1564733938518_27520480540254Get的值是:1564733938518_27520480540254······

生产者和消费者交替运行,生产者生产一个字符串,缓冲区为满,消费者消费一个字符串,缓冲区为空,循环往复,满足生产者/消费者模型。

await()/signal()生产者/消费者模型

缓冲区

public class ValueObject { public static String value = "";}

ThreadDomain48继承ReentrantLock,set方法生产,get方法消费

public class ThreadDomain48 extends ReentrantLock{ private Condition condition = newCondition(); public void set() { try { lock(); while (!"".equals(ValueObject.value)) condition.await(); ValueObject.value = "123"; System.out.println(Thread.currentThread().getName() + "生产了value, value的当前值是" + ValueObject.value); condition.signal(); } catch (InterruptedException e) { e.printStackTrace(); } finally { unlock(); } } public void get() { try { lock(); while ("".equals(ValueObject.value)) condition.await(); ValueObject.value = ""; System.out.println(Thread.currentThread().getName() + "消费了value, value的当前值是" + ValueObject.value); condition.signal(); } catch (InterruptedException e) { e.printStackTrace(); } finally { unlock(); } }}

MyThread41启动两个生产线程和一个消费线程

public class MyThread41 { public static void main(String[] args) { final ThreadDomain48 td = new ThreadDomain48(); Runnable producerRunnable = new Runnable() { public void run() { for (int i = 0; i < Integer.MAX_VALUE; i++) td.set(); } }; Runnable customerRunnable = new Runnable() { public void run() { for (int i = 0; i < Integer.MAX_VALUE; i++) td.get(); } }; Thread ProducerThread1 = new Thread(producerRunnable); ProducerThread1.setName("Producer1"); Thread ProducerThread2 = new Thread(producerRunnable); ProducerThread2.setName("Producer2"); Thread ConsumerThread = new Thread(customerRunnable); ConsumerThread.setName("Consumer"); ProducerThread1.start(); ProducerThread2.start(); ConsumerThread.start(); }}

输出结果如下

Producer1生产了value, value的当前值是123Consumer消费了value, value的当前值是Producer1生产了value, value的当前值是123

为什么Producer2无法生产,消费者无法消费呢?是因为此时缓冲区为满,Producer1的notify()应该唤醒Consumer却唤醒了Producer2,导致Producer2因为缓冲区为满和Consumer没有被唤醒而处于waiting状态,此时三个线程均在等待,出现了假死。

解决方案有两种:

1.让生产者唤醒所有线程,在set方法中使用condition.signalAll();

2.使用两个Condition,生产者Condition和消费者Condition,唤醒指定的线程;

正常输入如下:

······Producer2生产了value, value的当前值是123Consumer消费了value, value的当前值是Producer2生产了value, value的当前值是123Consumer消费了value, value的当前值是Producer2生产了value, value的当前值是123Consumer消费了value, value的当前值是Producer1生产了value, value的当前值是123Consumer消费了value, value的当前值是Producer1生产了value, value的当前值是123Consumer消费了value, value的当前值是Producer1生产了value, value的当前值是123Consumer消费了value, value的当前值是Producer1生产了value, value的当前值是123Consumer消费了value, value的当前值是Producer1生产了value, value的当前值是123Consumer消费了value, value的当前值是······

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。

声明:本页内容来源网络,仅供用户参考;我单位不保证亦不表示资料全面及准确无误,也不保证亦不表示这些资料为最新信息,如因任何原因,本网内容或者用户因倚赖本网内容造成任何损失或损害,我单位将不会负任何法律责任。如涉及版权问题,请提交至online#300.cn邮箱联系删除。

相关文章