基于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来创建 ...
随机推荐
- 输入框 input只能输入正数和小数点
输入框 input只能输入正数和小数点 限制文本框只能输入正数,负数,小数 onkeyup="value=value.replace(/[^\-?\d.]/g,'')" 限制文本 ...
- validate插件深入篇
1.使用valid()来验证表单是否填写正确: <form id="mainform"> <button id="check">< ...
- smarty 练习: 分页查询
对查出的数据进行分页,并添加查询 在main.php和main.html两个页面操作: 后台:main.php <?php include("../init.inc.php" ...
- 机器学习之python: kNN
################################################## # kNN : k Nearest Neighbour # Author : Monne # Da ...
- python中列表和字典的高级应用
1.将序列分解为单独的变量 1.1问题 包含n个元素的元组或列表.字符串.文件.迭代器.生成器,将它分解为n个变量 1.2方案 直接通过赋值操作 要求:变量个数要等于元素个数 当执行分解操作时,有时需 ...
- MLlib 卡方检验
1.卡方检验理论 1.1. 简介 总体的分布函数完全未知或只知形式.但不知其参数的情况,为了推断总体的某些未知特性,提出某些关于总体的假设.我们要根据样本对所提出的假设作出是接受,还是拒绝的决策.假 ...
- c++四则运算代码
//Code highlighting produced by Actipro CodeHighlighter (freeware)http://www.CodeHighlighter.com/--& ...
- 小公司生存,一般活过第一年,就能撑3年(读书笔记:成败关键,关键是你是否拥有现金流客户)good
小公司生存,一般活过第一年,就能撑3年,一般能撑过3年,到第7年遇到坎,如果第7年突破,能活过10年,是想死也不容易,等到第二个七年,可以搞搞人事地震了,因为要二次创业. -------------- ...
- android 截取指定位置字符串
String str = "s\ziyuan"; String newStr = str.subString(str.indexOf("\\"),str.len ...
- crontab,at命令,常见问题
crontab命令 前 一天学习了 at 命令是针对仅运行一次的任务,循环运行的例行性计划任务,linux系统则是由 cron (crond) 这个系统服务来控制的. Linux 系统上面原本就有非常 ...