`
xiao_hua
  • 浏览: 38643 次
  • 性别: 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)  

相关推荐

    wait和notify讲解

    wait和notify讲解

    Java 同步方式 wait和notify/notifyall

    下面是一个简单的生产者消费者模型示例,演示了`wait()`, `notify()` 的使用: ```java public class Buffer { private int data; private boolean available = false; public synchronized void put(int item)...

    java之wait,notify的用法([ 详解+实例 ])

    在Java多线程编程中,wait和notify是两个非常重要的方法,它们都是Object类的方法,用于线程之间的通信和同步。下面我们将详细解释wait和notify的用法。 wait方法 wait方法是Object类的一个方法,用于让当前线程...

    wait_notify_demo

    `wait()`、`notify()`和`notifyAll()`是Java中的三个关键字,它们属于Object类的方法,主要用于线程间的通信,尤其在实现生产者消费者模式时发挥着重要作用。本文将深入探讨这些方法以及如何在实际场景中应用它们。 ...

    java代码-wait-notify 生产者消费者

    在`main.java`文件中,我们可以预期看到具体的生产者和消费者线程类,以及它们如何使用`wait()`和`notify()`方法进行交互。`README.txt`可能是对代码的简单解释或使用指南。 了解并掌握生产者消费者模型和`wait-...

    java中几个notify、wait使用实例

    在Java的多线程编程中,`notify()`与`wait()`是实现线程间通信的重要方法,它们主要用于解决生产者消费者问题、读者写者问题等典型同步问题。这两个方法定义在`Object`类中,因此所有Java对象都可以作为锁来使用。在...

    Java多线程wait和notify

    在Java中,`wait()` 和 `notify()` 方法是实现线程间通信和协作的重要工具,它们属于 `java.lang.Object` 类,这意味着所有类都默认继承了这两个方法。本文将详细探讨如何使用 `wait()` 和 `notify()` 来控制子线程...

    如何在Java中正确使用 wait, notify 和 notifyAll

    举个例子,如果你的Java程序中有两个线程——即生产者和消费者,那么生产者可以通知消费者,让消费者开始消耗数据,因为队列缓冲区中有内容待消费(不为空)。相应的,消费者可以通知生产者可以开始生成更多的数据,...

    浅谈java多线程wait,notify

    CommunicationThread1是生产者线程,负责设置共享变量的值,而CommunicationThread2是消费者线程,负责读取共享变量的值。 在CommunicationThread1中,我们使用synchronized块来确保线程安全,并使用wait方法来暂停...

    Object类wait及notify方法原理实例解析

    生产者和消费者模式可以使用wait和notify方法来实现。 实现生产者和消费者模式时,需要使用synchronized关键字来确保线程安全。在生产者线程中,使用wait方法来等待仓库容量达到一定数量后再继续生产。在消费者线程...

    深入理解Wait、Notify和Wait与sleep区别

    在实际开发中,`wait()`, `notify()`和`notifyAll()`常用于实现生产者-消费者模型、哲学家就餐问题等经典并发问题。它们提供了一种精细控制线程间交互的方式,但使用时需谨慎,避免死锁和活锁的发生。 总之,理解和...

    Java的sychronized、wait和notify范例

    在实际开发中,`wait()`、`notify()`和`synchronized`常常用于实现生产者消费者模型、读写锁等高级并发场景。通过理解并熟练掌握这些概念,开发者可以编写出更加高效、可靠的多线程程序。 在提供的压缩包文件`java_...

    java生产者消费者

    使用synchronized关键字和wait()、notify()方法可以实现生产者消费者模式。生产者和消费者共享一个对象,这个对象包含一个计数器(表示缓冲区的大小)。生产者在生产完一个产品后调用notify()唤醒消费者,然后进入...

    生产者 消费者 进程 可视化 java

    完整的程序应该包括生产者和消费者线程如何处理 `wait()`, `notify()` 以及如何在适当的时候调用 `suspend()` 和 `resume()` 的逻辑。 在多线程环境中,可视化是一个有用的工具,可以帮助开发者观察和理解线程间的...

    java多线程实现生产者和消费者

    生产者和消费者线程都需要有自己的业务逻辑,这可以通过重写`run()`方法实现。 2. **共享资源**:在生产者-消费者模型中,通常会有一个固定大小的缓冲区作为共享资源。可以使用数组或链表实现,但需要注意的是,当...

    生产者 消费者 模式 c++

    7. 在适当的位置调用`std::condition_variable`的`wait`和`notify_one`/`notify_all`方法,实现线程的阻塞和唤醒。 在实际应用中,我们还可以引入“忙等待”(busy-waiting)或“信号量”(semaphores)来优化同步...

    wait()、notify()和notifyAll()方法1---马克-to-win java视频

    wait()、notify()和notifyAll()方法1---马克-to-win java视频

    java生产者与消费者实验报告

    通过`wait()`和`notify()`方法实现生产者与消费者间的线程同步,确保数据的正确生产和消费。 #### 实验步骤 1. **环境搭建**:在Eclipse中创建一个新的Java项目,命名为`program`。 2. **定义生产者类**:创建三个...

    生产者消费者问题c++实现

    生产者消费者问题是多线程编程中的一个经典案例,它展示了如何通过线程间的协作来解决资源的同步和异步操作。在C++中,我们可以利用标准库中的互斥量(mutex)、条件变量(condition_variable)等工具来实现这个问题...

    JAVA实现线程间同步与互斥生产者消费者问题

    `put()`和`take()`方法分别用于生产者添加和消费者取出元素,它们会自动处理阻塞和唤醒线程。 5. **Condition接口**:`java.util.concurrent.locks.Condition`接口提供了更细粒度的线程控制,允许创建多个条件变量...

Global site tag (gtag.js) - Google Analytics