我编写了使用wait和notify实现生产者消费者问题的代码。它工作正常但问题是消费者线程在无限循环中运行并且即使在生产者线程完成并且消费者已经消耗了列表中的所有元素之后仍然保持等待。
public class Practice {
public static void main(String[] args) {
List<Employee> empList = new ArrayList<Employee>();
Thread producer = new Thread(new Producer(empList , 2) , "Producer");
Thread consumer = new Thread(new Consumer(empList , 2) , "Consumer");
producer.start();
consumer.start();
}
}
class Employee
{
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
class Producer implements Runnable
{
List<Employee> empList;
int size;
public Producer(final List<Employee> empList , final int size)
{
this.empList = empList;
this.size = size;
}
@Override
public void run()
{
for(int i=0; i<5;i++)
{
try {
produce(new Employee());
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
public void produce(Employee e) throws InterruptedException
{
synchronized(empList){
while(empList.size()==size) // If list is full then will have to wait
{
System.out.println("List is full "+Thread.currentThread().getName()+" Is waiting and" + " Size is "+empList.size());
empList.wait();
}
}
synchronized(empList)
{
System.out.println("Producing");
empList.add(e);
empList.notifyAll();
}
}
}
class Consumer implements Runnable
{
List<Employee> empList;
int size;
public Consumer(final List<Employee> empList , final int size)
{
this.empList = empList;
this.size = size;
}
@Override
public void run()
{
while(true)
{
try {
System.out.println("Consumed ");
consume();
Thread.sleep(50);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
public void consume() throws InterruptedException
{
synchronized(empList){
while(empList.isEmpty()) // If list is empty then will have to wait
{
System.out.println("List is empty "+Thread.currentThread().getName()+" Is waiting and " + "Size is "+empList.size());
empList.wait();
}
}
synchronized(empList)
{
empList.notifyAll();
empList.remove(0);
}
}
}
请告诉我如何在生产者完成之后停止我的消费者线程并且消费者已经消耗了列表中的所有元素。请帮我解释一下代码。提前致谢
答案 0 :(得分:0)
生产者 - 消费者习惯用法就是Poison Pill模式:生产者在完成生产后将一个神奇的值放入队列,然后退出。当消费者读取魔术值时,它会退出。
毒丸定义由生产者和消费者共享:
static final Employee POISON_PILL = new Employee();
制片:
public void run()
{
for(int i=0; i<5;i++)
{
produce(new Employee());
}
produce(POISON_PILL);
}
消费者:
public void consume() throws InterruptedException
{
synchronized(empList){
while(empList.isEmpty())
{
empList.wait();
}
}
synchronized(empList)
{
// Note == not .equals() is intended here
if (empList.remove(0) == POISON_PILL) {
// done consuming
}
empList.notifyAll();
}
}