这两天复习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. 思科27亿美元收购网络安全公司Sourcefire

    据国外媒体报道,思科于今日宣布将以27亿美元的总价收购网络安全公司Sourcefire,以加强自身在网络安全业务领域的优势,该交易将于今年下半年完成. [IT商业新闻网讯](记者 张良)7月23日消息 ...

  2. 通过枚举enum实现单例设计

    一.枚举 通过enum关键字来实现枚举,在枚举中需要注意的有: 1. 枚举中的属性必须放在最前面,一般使用大写字母表示 2. 枚举中可以和java类一样定义方法 3. 枚举中的构造方法必须是私有的 通 ...

  3. 优化JavaScript脚本的性能

    循环 循环是很常用的一个控制结构,大部分东西要依靠它来完成,在JavaScript中,我们可以使用for(;;),while(),for(in)三种循环,事实上,这三种循环中for(in)的效率极差, ...

  4. GetWindowText

    用于得到窗口中的数据 {// TODO: If this is a RICHEDIT control, the control will not// send this notification un ...

  5. if exists用法

    1 判断数据库是否存在Sql代码 if exists (select * from sys.databases where name = ’数据库名’)    drop database [数据库名] ...

  6. 如何解决mysql数据库8小时无连接自动关闭

    windows下打开my.ini,增加: interactive_timeout=28800000 wait_timeout=28800000 专家解答:MySQL是一个小型关系型数据库管理系统,由于 ...

  7. Python学习笔记七-错误和异常

    程序员总是和各种错误打交道,学习如何识别并正确的处理程序错误是很有必要的. 7.1错误和异常 1.错误 从软件方面来看,错误分为语法错误和逻辑错误两种.这两种错误都将导致程序无法正常进行下去,当Pyt ...

  8. AudioServicesPlaySystemSound音频服务—b

    对于简单的.无混音音频,AVAudio ToolBox框架提供了一个简单的C语言风格的音频服务.你可以使用AudioservicesPlaySystemSound函数来播放简单的声音.要遵守以下几个规 ...

  9. java中gson的简单使用

    把从数据库中查询的记录以JSON格式返回给客户端,在这里使用gson-2.2.4.jar包. 代码结构如下: 数据库结构如下: (1)User.java public class User { pri ...

  10. 51单片机C语言学习笔记7:关于.c文件和.h文件

    1)h文件作用 1 方便开发:包含一些文件需要的共同的常量,结构,类型定义,函数,变量申明: 2 提供接口:对一个软件包来说可以提供一个给外界的接口(例如: stdio.h). 2)h文件里应该有什么 ...