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 }
  • 相关阅读:
    PAT (Advanced Level) 1080. Graduate Admission (30)
    PAT (Advanced Level) 1079. Total Sales of Supply Chain (25)
    PAT (Advanced Level) 1078. Hashing (25)
    PAT (Advanced Level) 1077. Kuchiguse (20)
    PAT (Advanced Level) 1076. Forwards on Weibo (30)
    PAT (Advanced Level) 1075. PAT Judge (25)
    PAT (Advanced Level) 1074. Reversing Linked List (25)
    PAT (Advanced Level) 1073. Scientific Notation (20)
    PAT (Advanced Level) 1072. Gas Station (30)
    PAT (Advanced Level) 1071. Speech Patterns (25)
  • 原文地址:https://www.cnblogs.com/tarbitrary/p/4004651.html
Copyright © 2011-2022 走看看