这两天复习java线程时,把java里面的线程基本知识点与jdk1.5以后新添加的一些类的使用都了解了一下,借用生产者消费者的问题来将他们实践一下。

题目:(题目在csdn一大牛的空间找的)

生产者-消费者模式,这个食堂中只有1张桌子,同时最多放10个盘子,现在有4个厨师做菜,每做好一盘就往桌子上放(生产者将产品往仓库中放),而有6个食客不停地吃(消费者消费产品,为了说明问题,他们的食量是无的).一般而言,厨师200-400ms做出一盘菜,而食客要400-600ms吃完一盘.当桌子上放满了10个盘子后,所有厨师都不能再往桌子上放,而当桌子上没有盘子时,所有的食客都只好等待.

代码如下:

  1. package net.xicp.tarbitrary.producerandcustomer;
  2.  
  3. import java.util.LinkedList;
  4. import java.util.Random;
  5. import java.util.concurrent.Callable;
  6. import java.util.concurrent.ExecutionException;
  7. import java.util.concurrent.ExecutorService;
  8. import java.util.concurrent.Executors;
  9. import java.util.concurrent.FutureTask;
  10. import java.util.concurrent.TimeUnit;
  11. import java.util.concurrent.locks.Condition;
  12. import java.util.concurrent.locks.Lock;
  13. import java.util.concurrent.locks.ReentrantLock;
  14.  
  15. public class NewFeatureTest {
  16.  
  17. public static void main(String[] args) throws InterruptedException,
  18. ExecutionException {
  19. // 创建一个具有10个线程的线程池
  20. ExecutorService se = Executors.newFixedThreadPool(30);
  21. // 产生一张桌子,桌子的最大容量为10
  22. DiningTable table = new DiningTable(10);
  23. // 产生生产者对象
  24. Chef chef = new Chef(table);
  25. // 产生消费者对象
  26. Eater eater = new Eater(table);
  27.  
  28. //本例只是模拟10个生产者与10个消费者,并没有完全按照题目的意思来进行解答
  29. for (int i = 1; i < 11; i++) {
  30. final FutureTask cheafTask = new FutureTask(chef);
  31. final FutureTask eaterTask = new FutureTask(eater);
  32. // 启动一个生产者线程
  33. se.execute(cheafTask);
  34. // 启动一个消费者线程
  35. se.execute(eaterTask);
  36. // 启动一个线程监听当前生产者线程的结果
  37. se.execute(new Runnable() {
  38. @Override
  39. public void run() {
  40. try {
  41. String st = cheafTask.get();
  42. System.out.println(st);
  43. } catch (InterruptedException e) {
  44. e.printStackTrace();
  45. } catch (ExecutionException e) {
  46. e.printStackTrace();
  47. }
  48.  
  49. }
  50. });
  51. // 启动一个线程监听当前消费者线程的结果
  52. se.execute(new Runnable() {
  53. @Override
  54. public void run() {
  55. try {
  56. String st = eaterTask.get();
  57. System.out.println(st);
  58. } catch (InterruptedException e) {
  59. e.printStackTrace();
  60. } catch (ExecutionException e) {
  61. e.printStackTrace();
  62. }
  63. }
  64. });
  65. //有序地关闭前面已经启动的一些线程
  66. }
  67. se.shutdown();
  68. }
  69. }
  70.  
  71. class Chef implements Callable {
  72. private DiningTable t;
  73. private Random random = new Random();
  74.  
  75. public Chef(DiningTable table) {
  76. this.t = table;
  77. }
  78.  
  79. public DiningTable getT() {
  80. return t;
  81. }
  82.  
  83. public void setT(DiningTable t) {
  84. this.t = t;
  85. }
  86.  
  87. public Dish produce() {
  88. try {
  89. // 模拟做菜用的时间,200-400毫秒一道菜
  90. // 跟下面一句的效果一致
  91. TimeUnit.MILLISECONDS.sleep(200 + random.nextInt(201));
  92. // Thread.sleep(200 + random.nextInt(201));
  93. } catch (InterruptedException e) {
  94. e.printStackTrace();
  95. }
  96. Dish food = new Dish();
  97. return food;
  98. }
  99.  
  100. @Override
  101. public String call() throws Exception {
  102. for (int i = 0; i < 10; i++) {
  103. Dish food = produce();
  104. t.putFood(food);
  105. }
  106. return Thread.currentThread().getName() + "结束";
  107. }
  108.  
  109. }
  110.  
  111. class Eater implements Callable {
  112. private DiningTable t;
  113. private Random random = new Random();
  114.  
  115. public Eater(DiningTable table) {
  116. this.t = table;
  117. }
  118.  
  119. public DiningTable getT() {
  120. return t;
  121. }
  122.  
  123. public void setT(DiningTable t) {
  124. this.t = t;
  125. }
  126.  
  127. public void consume(Dish food) {
  128. try {
  129. // 模拟吃菜用的时间
  130. // 跟下面一句的效果一致
  131. TimeUnit.MILLISECONDS.sleep(400 + random.nextInt(201));
  132. // Thread.sleep(400 + random.nextInt(201));
  133. } catch (InterruptedException e) {
  134. e.printStackTrace();
  135. }
  136. }
  137.  
  138. @Override
  139. public String call() throws Exception {
  140. for (int i = 0; i < 10; i++) {
  141. Dish food = t.getFood();
  142. consume(food);
  143. }
  144.  
  145. return Thread.currentThread().getName() + "结束";
  146. }
  147.  
  148. }
  149.  
  150. class Dish {
  151. Random random = new Random();
  152.  
  153. private String foodName;
  154.  
  155. public Dish() {
  156. super();
  157. int posi = random.nextInt(name.length);
  158. this.foodName = name[posi];
  159. }
  160.  
  161. String name[] = { "巫山烤鱼", "清炒小白菜 ", "糖醋里脊", "手撕包菜", "拔丝香蕉", "水煮肉片", "酸菜鱼",
  162. "土豆肉片" };
  163.  
  164. public String getName() {
  165. return foodName;
  166. }
  167.  
  168. }
  169.  
  170. class DiningTable {
  171. // 装食物用的容器
  172. private LinkedList list = new LinkedList();
  173. // 定义最大放菜量
  174. private int maxSize;
  175. // 创建一把锁
  176. private Lock lock = new ReentrantLock();
  177. // 获得当前lock对象的 Condition 实例
  178. private Condition condition;
  179.  
  180. public Lock getLock() {
  181. return lock;
  182. }
  183.  
  184. public void setLock(Lock lock) {
  185. this.lock = lock;
  186. }
  187.  
  188. public Condition getCondition() {
  189. return condition;
  190. }
  191.  
  192. public void setCondition(Condition condition) {
  193. this.condition = condition;
  194. }
  195.  
  196. public LinkedList getList() {
  197. return list;
  198. }
  199.  
  200. public void setList(LinkedList list) {
  201. this.list = list;
  202. }
  203.  
  204. public int getMaxSize() {
  205. return maxSize;
  206. }
  207.  
  208. public void setMaxSize(int maxSize) {
  209. this.maxSize = maxSize;
  210. }
  211.  
  212. public DiningTable(int maxSize) {
  213. super();
  214. this.maxSize = maxSize;
  215. this.condition = lock.newCondition();
  216. }
  217.  
  218. public void putFood(Dish food) {
  219. // 先进行锁定, 与synchronize起的作用类似
  220. lock.lock();
  221. try {
  222. // 防止假唤醒
  223. while (list.size() >= maxSize) {
  224.  
  225. System.out.println( "菜已经上满了" + Thread.currentThread().getName() + ",让他们先吃,等消灭几盘再做菜");
  226. // 如果桌子的菜已经放满了,则让当前线程等待
  227. this.condition.await();
  228. }
  229. list.addLast(food);
  230. System.out.println(Thread.currentThread().getName() + "烹饪了"
  231. + food.getName());
  232. // 通知所有休眠的食客线程继续吃菜
  233. this.condition.signalAll();
  234. } catch (Exception e) {
  235. e.printStackTrace();
  236. } finally {
  237. // 解除锁定
  238. lock.unlock();
  239. }
  240. }
  241.  
  242. public Dish getFood() {
  243. // 先进行锁定, 与synchronize起的作用类似
  244. lock.lock();
  245. Dish dish = null;
  246. try {
  247. // 防止假唤醒
  248. while (list.size() <= 0) {
  249. System.out.println( "菜已经被吃光了" + Thread.currentThread().getName() + "歇会再吃");
  250.  
  251. // 如果桌子上已经没有菜了,则让当前线程等待
  252. this.condition.await();
  253. }
  254. dish = list.removeFirst();
  255. System.out.println(Thread.currentThread().getName() + "吃掉了"
  256. + dish.getName());
  257. // 通知所有休眠的做菜线程继续做菜
  258. this.condition.signalAll();
  259. } catch (Exception e) {
  260. e.printStackTrace();
  261. } finally {
  262. // 解除锁定
  263. lock.unlock();
  264. }
  265.  
  266. return dish;
  267. }
  268.  
  269. }

基于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. div边框阴影的实现【转载】

    box-shadow:阴影水平偏移值(可取正负值): 阴影垂直偏移值(可取正负值):阴影模糊值:阴影颜色: Firefox支持Box Shadow(阴影):-moz-box-shadow:2px 2p ...

  2. arclist标签和list标签区别

    很多站长朋友在刚入门织梦的时候对织梦的标签存在很多的困惑,关于arclist标签和list标签,甚至不知道啥时候用arclist,啥时用list标签.arclist 为自由列表,全局模板中都生效,一般 ...

  3. C语言初学 给已知公式求圆周率

    公式: 圆周率=1-1/3+1/5-1/7+......+1/(4n-3)-1/(4n-1) #include<stdio.h> #include<math.h> main() ...

  4. Flume笔记--示例(使用配置文件)

    例子参考资料:http://www.aboutyun.com/thread-8917-1-1.html 自定义sink实现和属性注入:http://www.coderli.com/flume-ng-s ...

  5. 简单讲解iOS应用开发中的MD5加密的相关使用

      简单讲解iOS应用开发中的MD5加密的相关使用   作者:文顶顶 字体:[增加 减小] 类型:转载 时间:2015-12-19 我要评论 这篇文章主要介绍了iOS应用开发中的MD5加密的相关使用, ...

  6. Android 自定义View 画圆 画线

    自定义一个DrawCircle继承View 实现构造方法: public DrawCircle(Context context) { super(context); this.mContext = c ...

  7. rsyslog Properties 属性:

    rsyslog Properties 属性: 数据项 在rsyslog 是被称为 "properties". 它们可以有不同的源, 最重要的是 那些来自接收的消息,但是还有其他. ...

  8. Linux企业级项目实践之网络爬虫(27)——多路IO复用

    与多线程和多进程相比,I/O多路复用的最大优势是系统开销小,系统不需要建立新的进程或者线程,也不必维护这些线程和进程. 主要应用: (1)客户程序需要同时处理交互式的输入和服务器之间的网络连接 (2) ...

  9. cocos2d-x 头文件中添加方法变量导致编译报错

    代码如下: HelloWorldScene.h #ifndef __HELLOWORLD_SCENE_H__#define __HELLOWORLD_SCENE_H__ #include " ...

  10. .net连接oracle(无客户端)

    使用DDTek.Oracle.dll可以在没有安装oracle客户端的情况下连接远程的oracle. string _conString = "Host=192.168.1.1;Port=1 ...