`
xiao_hua
  • 浏览: 37846 次
  • 性别: Icon_minigender_1
  • 来自: 深圳
社区版块
存档分类
最新评论

浅谈wait和notify方法(生产者和消费者案例)

阅读更多
java.lang.Object类提供了wait()、notify()、notifyAll()方法,这些方法只有在synchronized或synchronized代码块中才能使用,是否就会报java.lang.IllegalMonitorStateException异常。

当另外线程执行了某对象的notify方法之后,会唤醒在此对象等待池中的某个线程,使之成为可运行线程。notifyAll是唤醒在此对象等待池中所有的等待线程。

下面我们来看看一个比较经典的问题:生产者/消费者问题
问题描述如下:
      生产者将产品交给店员,而消费者从店员处取走产品,店员一次只能持有固定数量的产品,如果生产者生产了过多的产品,店员会叫生产者等一下,如果店中有空位放产品了再通知;如果店中没有产品了,店员会告诉消费者等一下,如果店中有产品了再通知消费者来取产品。

这里可能出现问题有以下两个:
1. 生产者比消费者快时,消费者会漏掉一些数据没有取到
2. 消费者比生产者快时,消费着会取相同的数据
/**
 * 理解wait和notify方法
 * 生产者(Producer)/消费者(Consumer)问题
 * @author admin
 *
 */
public class ProductTest 
{

	/**
	 * @param args
	 */
	public static void main(String[] args) 
	{
		Clerk clerk = new Clerk();
		Thread producerThread = new Thread(new Producer(clerk));
		Thread consumerThread = new Thread(new Consumer(clerk));
		
		producerThread.start();
		consumerThread.start();
	}
}

/**
 * 店员
 * @author admin
 *
 */
class Clerk 
{
	//最大产品数
	private static final int MAX_PRODUCT = 20;
	
	//最小产品数
	private static final int MIN_PRODUCT = 0;
	
	//默认为0个产品
	private int product = 0;
	
	
	/**
	 * 生产者生产出来的产品交给店员
	 */
	public synchronized void addProduect()
	{
		if(this.product >= MAX_PRODUCT)
		{
			try
			{
				wait();  
				System.out.println("产品已满,请稍候再生产");
			}
			catch(InterruptedException e)
			{
				e.printStackTrace();
			}
			return;
		}
		
		this.product++;
		System.out.println("生产者生产第" + this.product + "个产品.");
		notifyAll();   //通知等待区的消费者可以取出产品了
	}
	
	/**
	 * 消费者从店员取产品
	 */
	public synchronized void getProduct()
	{
		if(this.product <= MIN_PRODUCT)
		{
			try 
			{
				wait(); 
				System.out.println("缺货,稍候再取");
			} 
			catch (InterruptedException e) 
			{
				e.printStackTrace();
			}
			return;
		}
		
		System.out.println("消费者取走了第" + this.product + "个产品.");
		this.product--;
		notifyAll();   //通知等待去的生产者可以生产产品了
	}
}


/**
 * 生产品线程
 * @author admin
 *
 */
class Producer implements Runnable
{
	private Clerk clerk ;
	
	public Producer(Clerk clerk)
	{
		this.clerk = clerk;
	}
	
	public void run() 
	{
		System.out.println("生产者开始生产产品.");
		while(true)
		{
			try 
			{
				Thread.sleep((int)(Math.random() * 10) * 100);
			}
			catch (InterruptedException e) 
			{
				e.printStackTrace();
			}
			clerk.addProduect(); //生产产品
		}
	}
}

/**
 * 消费线程
 * @author admin
 *
 */
class Consumer implements Runnable
{

	private Clerk clerk;
	
	public Consumer(Clerk clerk)
	{
		this.clerk = clerk;
	}
	
	public void run() 
	{
		System.out.println("消费者开始取走产品.");
		while(true)
		{
			try 
			{
				Thread.sleep((int)(Math.random() * 10) * 100);
			}
			catch (InterruptedException e) 
			{
				e.printStackTrace();
			}
			clerk.getProduct();  //取产品
		}
	}
	
}



总结:
      对wait,notify,notifyAll方法理解可以为归纳为图所示



ps:最后一个o.notify是o.notifyAll,上传的时候没有注意到,抱歉了!
  • 大小: 40.9 KB
1
0
分享到:
评论
2 楼 itatkakaxi2 2015-09-10  
if(this.product <= MIN_PRODUCT)  
应该改为
while(this.product <= MIN_PRODUCT)  
1 楼 itatkakaxi2 2015-09-10  
if(this.product <= MIN_PRODUCT)  
应该改为
while(this.product <= MIN_PRODUCT)  

相关推荐

Global site tag (gtag.js) - Google Analytics