这两天复习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. 控件真的很好用,突然感觉自己以前研究Discuz!NT366源码的方式很2了

    控件真的很好用,突然感觉自己以前研究Discuz!NT366源码的方式很2了,就是按钮上的或其他控件上的图片哪里去了?

  2. python requests 基础学习

    首先,Python 标准库中的 urllib2 模块提供了你所需要的大多数 HTTP 功能,但是它的 API 不友好.它是为另一个时代.另一个互联网所创建的.它需要巨量的工作,甚至包括各种方法覆盖,来 ...

  3. JS函数定义与匿名函数的调用

    一.函数声明.函数表达式.匿名函数 函数声明:function fnName () {…};使用function关键字 声明一个函数,再指定一个函数名,叫函数声明. 函数表达式 var fnName ...

  4. Python 改变当前工作目录

    在shell里编辑: import os os.getcwd()   #取得当前工作目录 os.chdir(r'目标目录')   # os.chdir(r'd:\learnpy')

  5. ios app 开发中ipa重新签名步骤介绍-备

    作为一个app应用程序开发者,在app应用程序在苹果商店上架前总需要将安装包安装到ios机器上进行测试,这个时候我们就需要打包in house版本的ipa了,打包in house实际上是一个将ipa应 ...

  6. 用VBA读取Excel表格输出到格式化的xml文件中

    最近需要做一个一劳永逸的XML文档生成,给项目内部专用的,直接VBA方便了,才第一次用.现学现卖了....抽时间还是系统的学习下这方面的知识吧 输出到UTF-8编码的XML文档.并且换行符是Unix的 ...

  7. linux下so动态库一些不为人知的秘密

    linux 下有动态库和静态库,动态库以.so为扩展名,静态库以.a为扩展名.二者都使用广泛.本文主要讲动态库方面知识.    基本上每一个linux 程序都至少会有一个动态库,查看某个程序使用了那些 ...

  8. 用 O(1) 时间检测整数 n 是否是 2 的幂次。

    位操作 2的幂次数 2  10 4 100 8 1000 16 10000 ... 1 class Solution { 2 /* 3 * @param n: An integer 4 * @retu ...

  9. C#系列教程——switch定义及使用

    代码如下: using System; class Switch_Test { static void Main() { Console.WriteLine("box sizes: 1=Sm ...

  10. weblogic 的应用 常见问题处理 db2 链接不上(转载)

    xingkaistart weblogic10之Failed to initialize the application 'wss-1-1' due to error weblogic. Weblog ...