Java多线程——使用wait/notify实现生产者/消费者模式

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/kingslave1/article/details/78395697

场景描述:

生产者/消费者模式是进程与线程学习中相当经典的问题,在本文中场景设置如下:

有一个仓库(Repository),有若干个生产者(Producer)和若干个消费者(Consumer),生产者可以生产产品(Procuct)并存入(push)仓库,消费者可以从仓库取出(pop)并消费产品。

我希望通过使用synchronize锁机制与wait()/notifyAll()或notify()方法实现,代码如下。但实际测试中发现,当使用notify方法时,线程仅会通知最近使用的线程,时间一长就会变成仅有两个线程在实际运行。而使用notifyAll()方法时,仓库实际产品最大数量仅是创建的生产者的最大数量,却不能达到自己预先定义的最大数量,此处暂未想通。目测估计是我的线程唤醒方法调用的位置或者调用的方式有问题,正在努力解决中。



实现代码:

import java.util.ArrayList;

/**
 * 多生产者多消费者单仓库的生产者消费者模式
 * @author breezefaith
 *
 */
class Product{
	private int productId;

	public Product(int productId) {
		super();
		this.productId = productId;
	}

	@Override
	public String toString() {
		return "Product["+productId+"]";
	}

}

class Repository{
	private int maxSize;
	private ArrayList<Product> list;

	public Repository(int maxSize) {
		super();
		this.maxSize = maxSize;
		list=new ArrayList<>(maxSize);
	}
	public void setMaxSize(int maxSize) {
		if(maxSize<=list.size()) {
			System.err.println("New size is smaller than the original.");
			return;
		}
		ArrayList<Product> newList=new ArrayList<>(maxSize);
		newList.addAll(list);
		list=newList;
	}
	public int getMaxSize() {
		return maxSize;
	}
	public int getCurrentSize() {
		return list.size();
	}
	public void push(Product product) {
		list.add(product);
	}
	public Product pop() {
		return list.remove(0);
	}
}

class Producer extends Thread{
	private Repository repository;
	private static int productId;
	public Producer(Repository repository) {
		super();
		this.repository = repository;
	}

	public Product produce() {
		Product product=new Product(productId++);
		System.out.println("生产者 "+Thread.currentThread().getName()+" 生产了产品 "+product+",剩余:"+(repository.getCurrentSize()+1));
		return product;
	}

	@Override
	public void run() {
		synchronized (repository) {
			try {
				while(true) {
					Thread.sleep(1000);
					if(repository.getCurrentSize()<repository.getMaxSize()) {
						repository.push(produce());
					}else {
						System.err.println("Producer "+Thread.currentThread().getName()+" want to produce a product, but repository is full.");
					}
					repository.notifyAll();
					repository.wait();
				}
			}catch(InterruptedException e) {
				e.printStackTrace();
			}
		}
	}

}

class Consumer extends Thread{
	private Repository repository;

	public Consumer(Repository repository) {
		super();
		this.repository = repository;
	}

	public Product consume() {
		Product product=repository.pop();
		System.out.println("消费者 "+Thread.currentThread().getName()+" 消费了产品 "+product+",剩余:"+repository.getCurrentSize());
		return product;
	}

	@Override
	public void run() {
		synchronized (repository) {
			try {
				while(true) {
					Thread.sleep(1000);
					if(repository.getCurrentSize()>0) {
						consume();
					}else {
						System.err.println("Consumer "+Thread.currentThread().getName()+" consume a product, but repository is empty.");
					}
					repository.notifyAll();
					repository.wait();
				}
			}catch(InterruptedException e) {
				e.printStackTrace();
			}
		}
	}
}

public class Run {

	public static void main(String[] args) {
		Repository repository=new Repository(3);
		Producer p1=new Producer(repository),
				p2=new Producer(repository),
				p3=new Producer(repository);
		p1.setName("p1");
		p2.setName("p2");
		p3.setName("p3");
		
		Consumer c1=new Consumer(repository),
				c2=new Consumer(repository);
		c1.setName("c1");
		c2.setName("c2");
		
		p1.start();
		p2.start();
		p3.start();
		c1.start();
		c2.start();
	}

}


测试结果:

生产者 p1 生产了产品 Product[0],剩余:1
消费者 c1 消费了产品 Product[0],剩余:0
Consumer c2 consume a product, but repository is empty.
生产者 p3 生产了产品 Product[1],剩余:1
生产者 p2 生产了产品 Product[2],剩余:2
生产者 p3 生产了产品 Product[3],剩余:3
消费者 c2 消费了产品 Product[1],剩余:2
消费者 c1 消费了产品 Product[2],剩余:1
生产者 p1 生产了产品 Product[4],剩余:2
消费者 c1 消费了产品 Product[3],剩余:1
消费者 c2 消费了产品 Product[4],剩余:0
生产者 p3 生产了产品 Product[5],剩余:1
生产者 p2 生产了产品 Product[6],剩余:2
生产者 p3 生产了产品 Product[7],剩余:3
消费者 c2 消费了产品 Product[5],剩余:2
消费者 c1 消费了产品 Product[6],剩余:1
生产者 p1 生产了产品 Product[8],剩余:2





猜你喜欢

转载自blog.csdn.net/kingslave1/article/details/78395697