16 November 2014

一个生产者和消费者队列的编写

生产者和消费者是一个经典的并发应用场景,也是面试中的高频题目。 下面是一个同步队列,关键的点在代码中有注释。

public class T_SynList extends LinkedList<Item>{
	public static int MAX=5;
	public synchronized void produce(String producer)
	{
		System.out.println(producer+"操作");
		
		while(size()==MAX)
		{
			try {
				System.out.println(producer+"等待");
				wait();
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}
		add(new Item(producer,0));
		notify();
	}
	
	public synchronized Item consume(String consumer)
	{
		System.out.println(consumer+"操作");
		/*
		注意这里一定要是while不能是if。如果是if,考虑如下场景,消费者1,消费者2已经阻塞。这时生产者1生产了一个物品,唤醒消费者1和消费者2,消费者1消耗掉了商品,此时消费者2应该继续阻塞,但如果用if只判断一次就还会往下执行(被唤醒后进程沿着wait()方法向后执行)。。。
		现在问题来了,notify()到底唤醒几个进程?
		*/
		while(size()==0)
		{
			try {
				System.out.println(consumer+"等待");
				wait();
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}
		Item item=removeFirst();
		item.setConsumer(consumer);
		notify();
		return item;
	}
}

补充: 上面的注释中的观点部分是错误的。 在Stackoverflow 请教大神之后,首先notify()是只能唤醒一个进程,但是为什么不能将while改为if的原因是唤醒的消费者线程执行完会继续唤醒下一个消费者线程,对于这个消费者是不满足执行条件的,应该再次判断进行阻塞。



blog comments powered by Disqus