首页 > 代码库 > 基于java callable及future接口解决生产者消费者问题

基于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  @Override104  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  @Override144  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 }

 

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