Java多线程 生产者消费者模型实例详解
生产者消费者模型
生产者:生产任务的个体;
消费者:消费任务的个体;
缓冲区:是生产者和消费者之间的媒介,对生产者和消费者解耦。
当
缓冲区元素为满,生产者无法生产,消费者继续消费;
缓冲区元素为空,消费者无法消费,生产者继续生产;
wait()/notify()生产者消费者模型
制作一个简单的缓冲区ValueObject,value为空表示缓冲区为空,value不为空表示缓冲区满
publicclassValueObject{
publicstaticStringvalue="";
}
生产者,缓冲区满则wait(),不再生产,等待消费者notify(),缓冲区为空则开始生产
publicclassProducer{
privateObjectlock;
publicProducer(Objectlock)
{
this.lock=lock;
}
publicvoidsetValue()
{
try
{
synchronized(lock)
{
if(!ValueObject.value.equals(""))
lock.wait();
Stringvalue=System.currentTimeMillis()+"_"+System.nanoTime();
System.out.println("Set的值是:"+value);
ValueObject.value=value;
lock.notify();
}
}
catch(InterruptedExceptione)
{
e.printStackTrace();
}
}
}
消费者,缓冲区为空则wait(),等待生产者notify(),缓冲区为满,消费者开始消费
publicclassCustomer{
privateObjectlock;
publicCustomer(Objectlock)
{
this.lock=lock;
}
publicvoidgetValue()
{
try
{
synchronized(lock)
{
if(ValueObject.value.equals(""))
lock.wait();
System.out.println("Get的值是:"+ValueObject.value);
ValueObject.value="";
lock.notify();
}
}
catch(InterruptedExceptione)
{
e.printStackTrace();
}
}
}
main方法,启动一个生产者和一个消费者
publicclassMain{
publicstaticvoidmain(String[]args)
{
Objectlock=newObject();
finalProducerproducer=newProducer(lock);
finalCustomercustomer=newCustomer(lock);
RunnableproducerRunnable=newRunnable()
{
publicvoidrun()
{
while(true)
{
producer.setValue();
}
}
};
RunnablecustomerRunnable=newRunnable()
{
publicvoidrun()
{
while(true)
{
customer.getValue();
}
}
};
ThreadproducerThread=newThread(producerRunnable);
ThreadCustomerThread=newThread(customerRunnable);
producerThread.start();
CustomerThread.start();
}
}
运行结果如下
Set的值是:1564733938518_27520480474279 Get的值是:1564733938518_27520480474279 Set的值是:1564733938518_27520480498378 Get的值是:1564733938518_27520480498378 Set的值是:1564733938518_27520480540254 Get的值是:1564733938518_27520480540254 ······
生产者和消费者交替运行,生产者生产一个字符串,缓冲区为满,消费者消费一个字符串,缓冲区为空,循环往复,满足生产者/消费者模型。
await()/signal()生产者/消费者模型
缓冲区
publicclassValueObject{
publicstaticStringvalue="";
}
ThreadDomain48继承ReentrantLock,set方法生产,get方法消费
publicclassThreadDomain48extendsReentrantLock
{
privateConditioncondition=newCondition();
publicvoidset()
{
try
{
lock();
while(!"".equals(ValueObject.value))
condition.await();
ValueObject.value="123";
System.out.println(Thread.currentThread().getName()+"生产了value,value的当前值是"+ValueObject.value);
condition.signal();
}
catch(InterruptedExceptione)
{
e.printStackTrace();
}
finally
{
unlock();
}
}
publicvoidget()
{
try
{
lock();
while("".equals(ValueObject.value))
condition.await();
ValueObject.value="";
System.out.println(Thread.currentThread().getName()+"消费了value,value的当前值是"+ValueObject.value);
condition.signal();
}
catch(InterruptedExceptione)
{
e.printStackTrace();
}
finally
{
unlock();
}
}
}
MyThread41启动两个生产线程和一个消费线程
publicclassMyThread41{
publicstaticvoidmain(String[]args)
{
finalThreadDomain48td=newThreadDomain48();
RunnableproducerRunnable=newRunnable()
{
publicvoidrun()
{
for(inti=0;i
输出结果如下
Producer1生产了value,value的当前值是123
Consumer消费了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的当前值是123
Consumer消费了value,value的当前值是
Producer2生产了value,value的当前值是123
Consumer消费了value,value的当前值是
Producer2生产了value,value的当前值是123
Consumer消费了value,value的当前值是
Producer1生产了value,value的当前值是123
Consumer消费了value,value的当前值是
Producer1生产了value,value的当前值是123
Consumer消费了value,value的当前值是
Producer1生产了value,value的当前值是123
Consumer消费了value,value的当前值是
Producer1生产了value,value的当前值是123
Consumer消费了value,value的当前值是
Producer1生产了value,value的当前值是123
Consumer消费了value,value的当前值是
······
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持毛票票。