zoukankan      html  css  js  c++  java
  • 基于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 }
  • 相关阅读:
    AJAX学习笔记
    JQuery 学习笔记-2017.05.22
    十二.GUI
    十一.文件
    十.模块和库
    九.类的进化(魔法方法、特性和迭代器)
    八.异常
    七.类的继承
    六.函数和类
    五.条件、循环和其他语句
  • 原文地址:https://www.cnblogs.com/tarbitrary/p/4004651.html
Copyright © 2011-2022 走看看