【ThinkingInJava】62、生产者与消费者

/**
* 书本:《Thinking In Java》
* 功能:生产者与消费者:
* 		请考虑这样一个人饭店,它有一个厨师和一个服务员。这个服务员必须等待厨师准备好膳食。当厨师准备好时,他会通知服务员,之后服务员上菜,然后返回继续等待。
* 文件:Restaurant.java
* 时间:2015年5月8日18:23:01
* 作者:cutter_point
*/
package Lesson21Concurency;

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;

import static net.mindview.util.Print.*;

class Meal	//膳食类
{
	private final int orderNum;	//点餐的数量
	public Meal(int orderNum) { this.orderNum = orderNum; }	//初始化,餐点的数量
	public String toString() { return "Meal " + this.orderNum; }
}

//客人类
class WaitPerson implements Runnable
{
	private Restaurant restaurant;	//一个餐厅类
	public WaitPerson(Restaurant r) { restaurant = r; }		//构造函数,客人要去的餐厅在哪?

	@Override
	public void run()
	{
		//对于一个客人来说,就是等待自己的食物
		try
		{
			while(!Thread.interrupted()) 		//只要线程没有被中断
			{
				synchronized(this)	//当取得了客人这个线程的时候
				{
					while(restaurant.meal == null) 		//没有食物了
						this.wait(); 	//等待厨师做好食物
				}
				print("客人得到了 " + restaurant.meal);		//客人得到了食物,准备吃饭
				synchronized(restaurant.chef)
				{
					restaurant.meal = null;		//食物买完了
					restaurant.chef.notifyAll(); 	//食物卖完了,唤醒厨师赶紧做食物
				}
			}
		}
		catch (InterruptedException e)
		{
			print("客人没食物吃,走了!");
		}
	}

}

class Chef implements Runnable
{
	private Restaurant restaurant;		//厨师所在的餐厅
	private int count = 0;

	public Chef(Restaurant restaurant)
	{
		this.restaurant = restaurant;
	}

	@Override
	public void run()
	{
		//首先线程不能被中断
		try
		{
			while(!Thread.interrupted())
			{
				//当线程没有被中断的时候
				synchronized(this)	//给这个块上锁,当没有得到当前对象的锁的时候,不能执行
				{
					while(restaurant.meal != null)
						this.wait();		//线程进入等待,只要还有食物,那么就得等待
				}

				//当被调用了10次的时候,那么就说食物吃完了,关门大吉
				if(++count == 10)
				{
					print("食物卖完了,关门大吉");
					//停止线程
//					restaurant.exec.shutdown();
					restaurant.exec.shutdownNow();		//这个函数是向所有的由ExecutorService启动的任务发送interrupt中断请求
				}
				printnb("上菜啦!");	//当没有被调用10次的时候,还有食物
				synchronized(restaurant.waitPerson) 	//当线程取得这个餐厅里面的客人对象的时候
				{
					restaurant.meal = new Meal(count);		//生产第count套食物
					restaurant.waitPerson.notifyAll();  	//唤醒客人,可以开始吃饭了
				}
				TimeUnit.MILLISECONDS.sleep(100); 		//休息100毫秒
			}
		}
		catch (InterruptedException e)
		{
			print("厨师被炒鱿鱼了!");
		}
	}
}

//餐厅类
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();		//投入建立一家餐厅
	}
}

输出:

上菜啦!-obj2 客人得到了 Meal 1  obj1

上菜啦!-obj2 客人得到了 Meal 2  obj1

上菜啦!-obj2 客人得到了 Meal 3  obj1

上菜啦!-obj2 客人得到了 Meal 4  obj1

上菜啦!-obj2 客人得到了 Meal 5  obj1

上菜啦!-obj2 客人得到了 Meal 6  obj1

上菜啦!-obj2 客人得到了 Meal 7  obj1

上菜啦!-obj2 客人得到了 Meal 8  obj1

上菜啦!-obj2 客人得到了 Meal 9  obj1

食物卖完了,关门大吉  obj1

上菜啦!-obj2 客人没食物吃,走了!  obj1

厨师被炒鱿鱼了!  obj1

时间: 2024-09-28 04:51:51

【ThinkingInJava】62、生产者与消费者的相关文章

生产者与消费者模式

1 准确说应该是生产者(setter)-消费者(getter)-仓储模型,离开了仓储,生产者消费者模型就显得没有说服 2 力了. 3 >实现代码: 4 5 //1. 实体设计:同步栈仓储,共享数据域 6 class SyncStack{ 7 8 //同步栈仓储中的数据产品,默认为10个大小 9 private String[] products=new String[10]; 10 //数据产品数据的下标索引,初始化为0 11 private int index=0; 12 13 //sette

多线程编程之生产者和消费者之间的问题

前段时间没事研究了一些生产者和消费者之间的问题,期间也查看了不少资料.又重新有了新的认识.特别作为一个IT农民工,必须要掌握的技能啊. 个人理解,这个应该说是一种模型吧,学会它,可以应用到多个方面的技术上去.数据流文件的读写,程序中的数据缓冲技术,播放缓冲技术等等. 废话不多说...直接上代码.下面是个C# 写的代码.比较粗糙,请谅解,有问题大家可以一起讨论研究. 1 using System; 2 using System.Threading; 3 4 namespace Consumer 5

Java线程学习整理--4---一个简单的生产者、消费者模型

 1.简单的小例子: 下面这个例子主要观察的是: 一个对象的wait()和notify()使用情况! 当一个对象调用了wait(),那么当前掌握该对象锁标记的线程,就会让出CPU的使用权,转而进入该对象的等待池中等待唤醒,这里说明一下,每一个对象都有一个独立的等待池和锁池! 等待池:上述的wait()后的线程会进入等待池中,处于下图线程声明周期(简单示意图) 中的这个状态,等待池中的线程任然具有对象的锁标记,但是处于休眠状态,不是可运行状态! 当该对象调用notify方法之后,就会在等待池中系统

生产者与消费者以及多个容器的多线程问题(经典 集合了老师,同学以及自己的想法)

1 package day2016_10_25_Thread; 2 3 import java.util.LinkedList; 4 import java.util.Random; 5 6 public class Productor { 7 public static void main(String[] args) throws InterruptedException { 8 9 //多个容器 10 Box box = new Box(); 11 Box box2 = new Box()

生产者与消费者问题解决:解决先打印出消费的情况

有bug 的代码(马士兵老师讲解的): 1 <span style="font-size:14px;">/**生产者消费者问题,涉及到几个类 2 * 第一,这个问题本身就是一个类,即主类 3 * 第二,既然是生产者.消费者,那么生产者类和消费者类就是必须的 4 * 第三,生产什么,消费什么,所以物品类是必须的,这里是馒头类 5 * 第四,既然是线程,那么就不是一对一的,也就是说不是生产一个消费一个,既然这样,多生产的往哪里放, 6 * 现实中就是筐了,在计算机中也就是数据结

java_Thread生产者与消费者 Demo

1 package com.bjsxt.Thread.Demo; 2 public class ProducerConsumer { 3 /** 4 * 生产者与消费者 5 * @param args 6 */ 7 public static void main(String[] args) {// 模拟线程 8 SyncStack ss = new SyncStack(); 9 Producer p = new Producer(ss); 10 Consumer c = new Consume

生产者和消费者问题(2)

1 //生产者和消费者问题 2 //使用环形队列 3 //解决了生产过剩的问题 4 #include <stdio.h> 5 #include <semaphore.h> 6 #include <pthread.h> 7 #include <stdlib.h> 8 #include <time.h> 9 #include <unistd.h> 10 11 //定义环形队列类型 12 #define Q_MAX 7 13 typedef

Boost lockfree deque 生产者与消费者多对多线程应用

boost库中有一个boost::lockfree::queue类型的 队列,对于一般的需要队列的程序,其效率都算不错的了,下面使用一个用例来说明. 程序是一个典型的生产者与消费者的关系,都可以使用多线程,其效率要比使用上层的互斥锁要快很多,因为它直接使用底层的原子操作来进行同步数据的. freedeque.h 1 #pragma once#ifndef INCLUDED_UTILS_LFRINGQUEUE 2 #define INCLUDED_UTILS_LFRINGQUEUE 3 4 #de

多线程操作实例——生产者与消费者

面对多线程学习生产者与消费者是最基本的实例 对于java后端开发的人员必须要掌握,还有考研考试计算机操作系统的同鞋. 下面是三个实例对于生产者与消费者的的例子,层层递进,逐步解决问题. 问题:生产者——设置信息名字name,和内容content 消费者——负责取出设置的信息. 一.基本实现 由于线程的不确定性可能出现以下问题: (1)消费者取出的信息不匹配,即不是由同一个生产者设置的信息 (2)生产者生产了多个信息,消费者才开始取出信息,或消费者取出的重复的信息. 上面的问题下面会逐一解决,下面