基于java callable及future接口解决生产者消费者问题

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

 

posted @ 2014-10-03 00:31  tarbitrary  阅读(593)  评论(0编辑  收藏  举报