这两天复习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接口解决生产者消费者问题的更多相关文章

  1. java使用synchronized与Semaphore解决生产者消费者问题对比

    一.synchronized与信号量Semaphore简介 1.synchronized是java中的关键字,是用来控制线程同步的问题最常用的方法. 2.Semaphore是属于java的一个类,同样 ...

  2. java多线程解决生产者消费者问题

    import java.util.ArrayList; import java.util.List; /** * Created by ccc on 16-4-27. */ public class ...

  3. Java如何使用线程解决生产者消费者问题?

    在Java编程中,如何使用线程解决生产者消费者问题? 以下示例演示如何使用线程解决生产者消费者问题. package com.yiibai; public class ProducerConsumer ...

  4. Java Thread系列(十)生产者消费者模式

    Java Thread系列(十)生产者消费者模式 生产者消费者问题(producer-consumer problem),是一个多线程同步问题的经典案例.该问题描述了两个共亨固定大小缓冲区的线程-即所 ...

  5. Linux多线程实践(六)使用Posix条件变量解决生产者消费者问题

    前面的一片文章我们已经讲过使用信号量解决生产者消费者问题.那么什么情况下我们须要引入条件变量呢? 这里借用  http://www.cnblogs.com/ngnetboy/p/3521547.htm ...

  6. Java并发编程:Future接口、FutureTask类

    在前面的文章中我们讲述了创建线程的2种方式,一种是直接继承Thread,另外一种就是实现Runnable接口. 这2种方式都有一个缺陷就是:在执行完任务之后无法获取执行结果. 如果需要获取执行结果,就 ...

  7. Java Callable和Future简述

    创建线程的两种方式,一种是直接继承Thread,另外一种就是实现Runnable接口.这两种方式都有一个缺陷就是:在执行完任务之后无法获取执行结果.如果需要获取执行结果,就必须通过共享变量或者使用线程 ...

  8. Java 管程解决生产者消费者问题

    同样是实验存档.//.. 依然以生产者消费者问题作为背景. 管程(=“资源管理程序”)将资源和对资源的操作封装起来,资源使用者通过接口操作资源就 ok,不用去考虑进程同步的问题. 管程: packag ...

  9. 使用Callable和Future接口创建线程

    具体是创建Callable接口的实现类,并实现clall()方法.并使用FutureTask类来包装Callable实现类的对象,且以此FutureTask对象作为Thread对象的target来创建 ...

随机推荐

  1. PHP如何防止SQL注入及开发安全 53

    PHP如何防止SQL注入及开发安全 [php]  function inject_check($sql_str) {     $check=eregi('select|insert|update|de ...

  2. 【行为型】Chain of responsibility模式

    职责链模式将对象的请求处理组成链式结构,并将请求按链式结构逐个传递下去,直接被其中的某个处理者处理为止.由此可知,职责链模式的适用场合是对指定请求,可以有多个请求处理者(或称为请求响应者),但用户并不 ...

  3. Array and its point.

    a is the array name. &a is the ponit of 2-D array which contains a[5]. the type of &a should ...

  4. LINUX的命令(未完待续)

    遇到忘了的Linux命令,复习之后,把它记在这里,供以后复习. ^C:刚开始在看视频的时候发现上面有cd ^C,还以为这是个什么命令,其实^C这不是输入进去的,当你按了Ctrl+C之后就会出现^C,C ...

  5. FPGA那些事 --经典总结

    规范很重要 工作过的朋友肯定知道,公司里是很强调规范的,特别是对于大的设计(无论软件还是硬件),不按照规范走几乎是不可实现的.逻辑设计也是这样:如果不按规范做的话,过一个月后调试时发现有错,回头再看自 ...

  6. NGUI类之间的关系和架构

    NGUI Drawcall 1.使用同一个altals的元素尽量放在同一个UIPanel下面,在NGUI中,它消耗的drawcall是以每个Panel为独立计算单位进行计算的. 2.如果一个UIPan ...

  7. RTSP Monitor的总结

    项目描述: 一个本地的IP  Camera 实时发送RTSP视频流到本机上,视频的帧是H264编码,需要解码并显示到屏幕上.并把每帧视频对应的时间戳转换成日期年月日时分秒打印到每帧的图像上显示. 使用 ...

  8. Qt编程之右键单击QTreeWidgetItem弹出菜单

    其实有这个需求很好理解,就是我有个project manager,上面的TreeWidgetItem都表示一个工程,我需要右键创建新的工程,或者删除.这个在很多普通软件中也见得多.在弹出的菜单中加入相 ...

  9. ffdshow 源代码分析1 : 整体结构

    ffdshow是一个非常强大的DirectShow解码器,封装了ffmpeg,libmpeg2等解码库.它也提供了丰富的加工处理选项,可以锐化画面,调节画面的亮度等等.不止是视频,FFDShow现在同 ...

  10. 8.2.1.8 IS NULL Optimization NULL 优化:

    8.2.1.8 IS NULL Optimization NULL 优化: Oracle 对待null值: SQL> create table t100(id int,name char(10) ...