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

生产者消费者[简单示例]

 
阅读更多

class Meal{
	private final int orderNum;
	Meal(int orderNum){
		this.orderNum = orderNum;
	}
	public String toString(){
		return "Meal " + orderNum;
	}
}

class WaitPerson implements Runnable{
	private Restaurant restaurant;
	public WaitPerson(Restaurant r){
		restaurant = r;
	}
	public void run(){
		try {
			while (!Thread.interrupted()) {
				synchronized (this) {
					while (restaurant.meal == null)
						wait();
				}
				System.out.println("Waitperson got " + restaurant.meal);
				synchronized (restaurant.chef) {
					restaurant.meal = null;
					restaurant.chef.notifyAll(); // ready for another
				}
			}
		} catch (Exception e) {
			System.out.println("WaitPerson interrupted");
		}
	}
}
class Chef implements Runnable{
	private Restaurant restaurant;
	private int count = 0;
	public Chef(Restaurant r){
		restaurant = r;
	}
	public void run(){
		try {
			while(!Thread.interrupted()){
				synchronized(this){
					while(restaurant.meal!=null)
						wait(); 	// for the meal to be taken;
				}
				if(++count == 10){
					System.out.println("Out of fodd, clsosing");
					restaurant.exec.shutdownNow();
				}
				System.out.println("Order up! ");
				synchronized(restaurant.waitPerson){
					restaurant.meal = new Meal(count);
					restaurant.waitPerson.notifyAll();
				}
				TimeUnit.MILLISECONDS.sleep(100);
			}
		} catch (InterruptedException e) {
			System.out.println("Chef interrupted");
		}
	}
}

public class Restaurant {
	Meal meal;
	ExecutorService exec = Executors.newCachedThreadPool();
	WaitPerson waitPerson = new WaitPerson(this);
	Chef chef = new Chef(this);
	public Restaurant(){
		exec.execute(chef);
		exec.execute(waitPerson);
	}
	public static void main(String[] args) {
		new Restaurant();
	}
}

 

 

Restaurant是WaitPerson和Chef的焦点, 他们都必须子回到在为哪个Restaurant工作,

因为他们必须和这家饭店的“餐窗”打交道, 以便放置或拿取restaurant.meal。 在run()

中, WiatPerson进入wait()模式, 停止其任务, 直到被Chef的notifyAll()唤醒。

 

由于这是一个非常简单的程序,因此我们直到只有一个任务将在WaitPerson的锁上

等待,即WaitPerson任务自身。 出于这个原因, 理论上可以调用notify()而不是

notifyAll()。 但是,在更复杂的情况下,可能会有多个任务在某个特定对象上

等待,因此就不知道哪个任务应该被唤醒,因此,调用notifyAll()更安全些,

这样可以唤醒等待这个锁的所有任务, 而每个任务都必须决定这个通知是否与

自己相关。

 

注意, wait()被包装在一个while()语句中, 这个语句在不断地测试正在等待的食物。

看上去有点怪-- 如果在等待一个订单,一旦被唤醒,这个订单就必须是可获得的,对嘛?

正如前面注意到的, 问题是在并发应用中, 某个洽谈的任务可能会在WaitPerson被唤醒,

会突然插足拿走订单,唯一安全的方式是使用下面这种wait()的惯用法

while(conditionIsNotMet)

wait();

 

对notifyAll()的调用必须首先捕获waitPerson上的锁, 而在WatiPerson.run()中

的对wati()的调用会自动地释放这个锁, 因此这是有可能实现的。 因为调用

notifyAll()必然拥有这个锁, 所以这保证两个试图在统一个对象上调用notifyAll()

的任务不会相互冲突。

 

通过把整个run()方法体放到一个try语句块中, 可使得这2个run()方法都被设计为

可以有序地关闭。 catch自居将紧挨着run()方法的结束括号之前结束,因此,如果这个任务

收到了InterruptedException异常, 它将在捕获异常之后立即结束。

 

注意, 在Chef中, 在调用shutdownNow()之后, 应该直接从run()中返回,并且通常这就是

你应该做的。 但是,以这种方式执行还有一些更有趣的东西。 shutdownNow()将向所有

由ExecutorService启动的任务发送interrupt(), 但是在Chef中,任务并没有获得该

interrupt()之后立即关闭, 因为当任务试图进入一个(可中断的)阻塞操作时,这个

中断只能抛出InterruptedException。 因此, 将看到首先显示了 "Order up!",然后

当Chef试图调用Slee()时, 抛出了InterruptedException. 如果移除对slee()的调用,

那么这个任务将回到run()循环的顶部,并由于Thread.interrupted()测试而退出,

同时并不抛出异常。


分享到:
评论

相关推荐

    生产者和消费者模式多线程

    创建一个简单的生产者消费者模型,可以使用以下伪代码: ```java class Producer implements Runnable { private final BlockingQueue<String> queue; public Producer(BlockingQueue<String> queue) { this....

    Java多线程实现生产者消费者

    本示例中的“生产者-消费者”模型是一种经典的多线程问题,它模拟了实际生产环境中的资源分配与消耗过程。下面我们将详细探讨如何在Java中实现这个模型。 首先,我们要理解生产者-消费者模型的基本概念。在这个模型...

    java生产者消费者

    下面是一个简单的wait/notify实现生产者消费者模式的代码示例: ```java import java.util.LinkedList; import java.util.Queue; public class ProducerConsumer { private Queue<Integer> queue = new ...

    生产者消费者实现 Linux实现

    "生产者消费者实现 Linux实现" 生产者消费者问题是计算机科学中一个经典的问题,旨在解决多个生产者和消费者之间的同步问题。 在 Linux 操作系统下实现生产者消费者算法是该问题的一种解决方案。 生产者消费者问题...

    Java实现简易生产者消费者模型过程解析

    在本文中,我们将通过一个简单的示例代码介绍Java实现简易生产者消费者模型的过程。 二、Java实现生产者消费者模型 在Java中,生产者消费者模型可以通过使用同步机制和wait/notify机制来实现。在下面的示例代码中...

    Linux进程间通信之生产者消费者

    "生产者消费者"问题是一个经典的多线程或进程同步问题,它用于演示和理解各种IPC机制。在这个场景中,生产者进程负责生成数据,而消费者进程则消费这些数据。下面我们将深入探讨Linux下的几种主要的IPC方法,以及...

    wpf窗体多线程实现生产者消费者模型

    以下是一个简单的示例,展示了如何在生产者消费者模型中应用这些概念: 1. 创建一个队列来存储数据。 2. 初始化一个信号量,例如:`Semaphore semaphore = new Semaphore(0, int.MaxValue);` 3. 生产者线程生成数据...

    生产者消费者多线程代码

    下面是一个简单的伪代码示例,展示了如何使用互斥锁和条件变量实现生产者消费者模式: ```python import threading buffer_size = 10 buffer = [None] * buffer_size count = 0 lock = threading.Lock() not_full ...

    C#写的生产者消费者问题

    生产者消费者问题是多线程编程中的经典模型,用于展示如何有效地在并发环境下共享资源。这个问题源于现实世界的仓库模型,其中生产者负责生产商品,而消费者则负责消费这些商品。仓库作为一个缓冲区,存储有限的商品...

    java多线程实现生产者消费者关系

    以下是一个简单的基于synchronized关键字和wait/notify机制的生产者消费者示例: ```java import java.util.LinkedList; public class ProducerConsumerExample { private final LinkedList<Object> buffer = new...

    java 多线程 生产者消费者模式

    以下是一段简单的生产者消费者模式的代码示例: ```java import java.util.concurrent.BlockingQueue; import java.util.concurrent.LinkedBlockingQueue; public class ProducerConsumerExample { public static...

    计算机操作系统 利用信号量机制模拟 生产者与消费者问题

    在计算机操作系统领域,生产者-消费者问题是经典的多线程同步问题,它展示了如何通过共享资源在并发环境中协调不同进程的行为。在这个问题中,"生产者"进程负责生成数据,而"消费者"进程则负责消费这些数据。为了...

    kafka-java-demo 基于java的kafka生产消费者示例

    在"Kafka-java-demo"中,你将看到如何使用这些接口来实现一个简单的生产者和消费者示例。 【Kafka Producer】 Kafka生产者是负责将数据发布到Kafka主题的组件。在Java中,我们可以创建一个Producer实例,配置相关...

    生产者消费者 C#做的

    - 以下是一个简单的使用`Channel`实现的生产者消费者模型的代码示例: ```csharp var channel = Channel.CreateBounded(10); // 创建一个容量为10的Channel Task.Run(async () => // 生产者线程 { for (int i...

    java生产者与消费者问题

    下面是一个简单的生产者消费者模型实现: ```java import java.util.concurrent.ArrayBlockingQueue; public class ProducerConsumerExample { public static void main(String[] args) { ArrayBlockingQueue...

    生产者与消费者问题

    6. **示例代码**:一个简单的生产者消费者实现可能会包含两个线程,一个生产者线程负责将数据放入队列,一个消费者线程负责从队列中取出数据。每个线程都会在适当的时机调用`wait()`和`notify()`或`notifyAll()`来...

    windows编程 PV操作 直观实现生产者与消费者

    在Windows编程领域,生产者-消费者问题是多线程并发控制的经典案例。这个问题涉及到多个线程(生产者和消费者)共享一个有限的资源池,生产者生产数据,而消费者消费这些数据。PV操作,即信号量(Semaphore)的概念...

    VC中的生产和消费问题.rar_vc 算法_生产 消费_生产者和消费者_生产者和消费者问题_生产者消费者

    在计算机科学中,生产者-消费者问题是多线程编程领域中的一个经典问题,它涉及到并发控制和同步。这个问题描述了两个或多个线程(生产者和消费者)如何共享一个有限的资源,通常是一个缓冲区。在VC(Visual C++)...

    vc 多个生产者和消费者问题

    以下是一个简单的步骤概述,展示如何在VC中使用事件对象解决多个生产者和消费者问题: 1. 定义一个有限大小的缓冲区,例如数组或链表,用于存储产品。 2. 创建两个事件对象:一个用于生产者,一个用于消费者。初始...

    生产者与消费者实例代码,线程学习必备

    `ProducerAndConsumer.zip`中的代码可能包含一个简单的Java实现,生产者类(Producer)和消费者类(Consumer)分别继承自Thread类,它们共享一个`BlockingQueue`实例。生产者类的run方法不断生成数据并调用`queue....

Global site tag (gtag.js) - Google Analytics