基于java callable及future接口解决生产者消费者问题
这两天复习java线程时,把java里面的线程基本知识点与jdk1.5以后新添加的一些类的使用都了解了一下,借用生产者消费者的问题来将他们实践一下。
题目:(题目在csdn一大牛的空间找的)
生产者-消费者模式,这个食堂中只有1张桌子,同时最多放10个盘子,现在有4个厨师做菜,每做好一盘就往桌子上放(生产者将产品往仓库中放),而有6个食客不停地吃(消费者消费产品,为了说明问题,他们的食量是无的).一般而言,厨师200-400ms做出一盘菜,而食客要400-600ms吃完一盘.当桌子上放满了10个盘子后,所有厨师都不能再往桌子上放,而当桌子上没有盘子时,所有的食客都只好等待.
代码如下:
- package net.xicp.tarbitrary.producerandcustomer;
- import java.util.LinkedList;
- import java.util.Random;
- import java.util.concurrent.Callable;
- import java.util.concurrent.ExecutionException;
- import java.util.concurrent.ExecutorService;
- import java.util.concurrent.Executors;
- import java.util.concurrent.FutureTask;
- import java.util.concurrent.TimeUnit;
- import java.util.concurrent.locks.Condition;
- import java.util.concurrent.locks.Lock;
- import java.util.concurrent.locks.ReentrantLock;
- public class NewFeatureTest {
- public static void main(String[] args) throws InterruptedException,
- ExecutionException {
- // 创建一个具有10个线程的线程池
- ExecutorService se = Executors.newFixedThreadPool(30);
- // 产生一张桌子,桌子的最大容量为10
- DiningTable table = new DiningTable(10);
- // 产生生产者对象
- Chef chef = new Chef(table);
- // 产生消费者对象
- Eater eater = new Eater(table);
- //本例只是模拟10个生产者与10个消费者,并没有完全按照题目的意思来进行解答
- for (int i = 1; i < 11; i++) {
- final FutureTask cheafTask = new FutureTask(chef);
- final FutureTask eaterTask = new FutureTask(eater);
- // 启动一个生产者线程
- se.execute(cheafTask);
- // 启动一个消费者线程
- se.execute(eaterTask);
- // 启动一个线程监听当前生产者线程的结果
- se.execute(new Runnable() {
- @Override
- public void run() {
- try {
- String st = cheafTask.get();
- System.out.println(st);
- } catch (InterruptedException e) {
- e.printStackTrace();
- } catch (ExecutionException e) {
- e.printStackTrace();
- }
- }
- });
- // 启动一个线程监听当前消费者线程的结果
- se.execute(new Runnable() {
- @Override
- public void run() {
- try {
- String st = eaterTask.get();
- System.out.println(st);
- } catch (InterruptedException e) {
- e.printStackTrace();
- } catch (ExecutionException e) {
- e.printStackTrace();
- }
- }
- });
- //有序地关闭前面已经启动的一些线程
- }
- se.shutdown();
- }
- }
- class Chef implements Callable {
- private DiningTable t;
- private Random random = new Random();
- public Chef(DiningTable table) {
- this.t = table;
- }
- public DiningTable getT() {
- return t;
- }
- public void setT(DiningTable t) {
- this.t = t;
- }
- public Dish produce() {
- try {
- // 模拟做菜用的时间,200-400毫秒一道菜
- // 跟下面一句的效果一致
- TimeUnit.MILLISECONDS.sleep(200 + random.nextInt(201));
- // Thread.sleep(200 + random.nextInt(201));
- } catch (InterruptedException e) {
- e.printStackTrace();
- }
- Dish food = new Dish();
- return food;
- }
- @Override
- public String call() throws Exception {
- for (int i = 0; i < 10; i++) {
- Dish food = produce();
- t.putFood(food);
- }
- return Thread.currentThread().getName() + "结束";
- }
- }
- class Eater implements Callable {
- private DiningTable t;
- private Random random = new Random();
- public Eater(DiningTable table) {
- this.t = table;
- }
- public DiningTable getT() {
- return t;
- }
- public void setT(DiningTable t) {
- this.t = t;
- }
- public void consume(Dish food) {
- try {
- // 模拟吃菜用的时间
- // 跟下面一句的效果一致
- TimeUnit.MILLISECONDS.sleep(400 + random.nextInt(201));
- // Thread.sleep(400 + random.nextInt(201));
- } catch (InterruptedException e) {
- e.printStackTrace();
- }
- }
- @Override
- public String call() throws Exception {
- for (int i = 0; i < 10; i++) {
- Dish food = t.getFood();
- consume(food);
- }
- return Thread.currentThread().getName() + "结束";
- }
- }
- class Dish {
- Random random = new Random();
- private String foodName;
- public Dish() {
- super();
- int posi = random.nextInt(name.length);
- this.foodName = name[posi];
- }
- String name[] = { "巫山烤鱼", "清炒小白菜 ", "糖醋里脊", "手撕包菜", "拔丝香蕉", "水煮肉片", "酸菜鱼",
- "土豆肉片" };
- public String getName() {
- return foodName;
- }
- }
- class DiningTable {
- // 装食物用的容器
- private LinkedList list = new LinkedList();
- // 定义最大放菜量
- private int maxSize;
- // 创建一把锁
- private Lock lock = new ReentrantLock();
- // 获得当前lock对象的 Condition 实例
- private Condition condition;
- public Lock getLock() {
- return lock;
- }
- public void setLock(Lock lock) {
- this.lock = lock;
- }
- public Condition getCondition() {
- return condition;
- }
- public void setCondition(Condition condition) {
- this.condition = condition;
- }
- public LinkedList getList() {
- return list;
- }
- public void setList(LinkedList list) {
- this.list = list;
- }
- public int getMaxSize() {
- return maxSize;
- }
- public void setMaxSize(int maxSize) {
- this.maxSize = maxSize;
- }
- public DiningTable(int maxSize) {
- super();
- this.maxSize = maxSize;
- this.condition = lock.newCondition();
- }
- public void putFood(Dish food) {
- // 先进行锁定, 与synchronize起的作用类似
- lock.lock();
- try {
- // 防止假唤醒
- while (list.size() >= maxSize) {
- System.out.println( "菜已经上满了" + Thread.currentThread().getName() + ",让他们先吃,等消灭几盘再做菜");
- // 如果桌子的菜已经放满了,则让当前线程等待
- this.condition.await();
- }
- list.addLast(food);
- System.out.println(Thread.currentThread().getName() + "烹饪了"
- + food.getName());
- // 通知所有休眠的食客线程继续吃菜
- this.condition.signalAll();
- } catch (Exception e) {
- e.printStackTrace();
- } finally {
- // 解除锁定
- lock.unlock();
- }
- }
- public Dish getFood() {
- // 先进行锁定, 与synchronize起的作用类似
- lock.lock();
- Dish dish = null;
- try {
- // 防止假唤醒
- while (list.size() <= 0) {
- System.out.println( "菜已经被吃光了" + Thread.currentThread().getName() + "歇会再吃");
- // 如果桌子上已经没有菜了,则让当前线程等待
- this.condition.await();
- }
- dish = list.removeFirst();
- System.out.println(Thread.currentThread().getName() + "吃掉了"
- + dish.getName());
- // 通知所有休眠的做菜线程继续做菜
- this.condition.signalAll();
- } catch (Exception e) {
- e.printStackTrace();
- } finally {
- // 解除锁定
- lock.unlock();
- }
- return dish;
- }
- }
基于java callable及future接口解决生产者消费者问题的更多相关文章
- java使用synchronized与Semaphore解决生产者消费者问题对比
一.synchronized与信号量Semaphore简介 1.synchronized是java中的关键字,是用来控制线程同步的问题最常用的方法. 2.Semaphore是属于java的一个类,同样 ...
- java多线程解决生产者消费者问题
import java.util.ArrayList; import java.util.List; /** * Created by ccc on 16-4-27. */ public class ...
- Java如何使用线程解决生产者消费者问题?
在Java编程中,如何使用线程解决生产者消费者问题? 以下示例演示如何使用线程解决生产者消费者问题. package com.yiibai; public class ProducerConsumer ...
- Java Thread系列(十)生产者消费者模式
Java Thread系列(十)生产者消费者模式 生产者消费者问题(producer-consumer problem),是一个多线程同步问题的经典案例.该问题描述了两个共亨固定大小缓冲区的线程-即所 ...
- Linux多线程实践(六)使用Posix条件变量解决生产者消费者问题
前面的一片文章我们已经讲过使用信号量解决生产者消费者问题.那么什么情况下我们须要引入条件变量呢? 这里借用 http://www.cnblogs.com/ngnetboy/p/3521547.htm ...
- Java并发编程:Future接口、FutureTask类
在前面的文章中我们讲述了创建线程的2种方式,一种是直接继承Thread,另外一种就是实现Runnable接口. 这2种方式都有一个缺陷就是:在执行完任务之后无法获取执行结果. 如果需要获取执行结果,就 ...
- Java Callable和Future简述
创建线程的两种方式,一种是直接继承Thread,另外一种就是实现Runnable接口.这两种方式都有一个缺陷就是:在执行完任务之后无法获取执行结果.如果需要获取执行结果,就必须通过共享变量或者使用线程 ...
- Java 管程解决生产者消费者问题
同样是实验存档.//.. 依然以生产者消费者问题作为背景. 管程(=“资源管理程序”)将资源和对资源的操作封装起来,资源使用者通过接口操作资源就 ok,不用去考虑进程同步的问题. 管程: packag ...
- 使用Callable和Future接口创建线程
具体是创建Callable接口的实现类,并实现clall()方法.并使用FutureTask类来包装Callable实现类的对象,且以此FutureTask对象作为Thread对象的target来创建 ...
随机推荐
- div边框阴影的实现【转载】
box-shadow:阴影水平偏移值(可取正负值): 阴影垂直偏移值(可取正负值):阴影模糊值:阴影颜色: Firefox支持Box Shadow(阴影):-moz-box-shadow:2px 2p ...
- arclist标签和list标签区别
很多站长朋友在刚入门织梦的时候对织梦的标签存在很多的困惑,关于arclist标签和list标签,甚至不知道啥时候用arclist,啥时用list标签.arclist 为自由列表,全局模板中都生效,一般 ...
- C语言初学 给已知公式求圆周率
公式: 圆周率=1-1/3+1/5-1/7+......+1/(4n-3)-1/(4n-1) #include<stdio.h> #include<math.h> main() ...
- Flume笔记--示例(使用配置文件)
例子参考资料:http://www.aboutyun.com/thread-8917-1-1.html 自定义sink实现和属性注入:http://www.coderli.com/flume-ng-s ...
- 简单讲解iOS应用开发中的MD5加密的相关使用
简单讲解iOS应用开发中的MD5加密的相关使用 作者:文顶顶 字体:[增加 减小] 类型:转载 时间:2015-12-19 我要评论 这篇文章主要介绍了iOS应用开发中的MD5加密的相关使用, ...
- Android 自定义View 画圆 画线
自定义一个DrawCircle继承View 实现构造方法: public DrawCircle(Context context) { super(context); this.mContext = c ...
- rsyslog Properties 属性:
rsyslog Properties 属性: 数据项 在rsyslog 是被称为 "properties". 它们可以有不同的源, 最重要的是 那些来自接收的消息,但是还有其他. ...
- Linux企业级项目实践之网络爬虫(27)——多路IO复用
与多线程和多进程相比,I/O多路复用的最大优势是系统开销小,系统不需要建立新的进程或者线程,也不必维护这些线程和进程. 主要应用: (1)客户程序需要同时处理交互式的输入和服务器之间的网络连接 (2) ...
- cocos2d-x 头文件中添加方法变量导致编译报错
代码如下: HelloWorldScene.h #ifndef __HELLOWORLD_SCENE_H__#define __HELLOWORLD_SCENE_H__ #include " ...
- .net连接oracle(无客户端)
使用DDTek.Oracle.dll可以在没有安装oracle客户端的情况下连接远程的oracle. string _conString = "Host=192.168.1.1;Port=1 ...