zoukankan      html  css  js  c++  java
  • 多线程生产者消费者实例

    • 目的

            生产者和消费者实例主要是练习synchronized、wait、notify或notifyAll、join等的使用,实际感受他们的用途。这例子自己随意写的,也没想到写得多么完善,只是为了练习。大家将就看看吧,哈哈!


    • 食物类
     1 package thread.producer.customer;
     2 
     3 public class Food {
     4 
     5     private String name;
     6 
     7     public String getName() {
     8         return name;
     9     }
    10 
    11     public void setName(String name) {
    12         this.name = name;
    13     }
    14     
    15     
    16 }
    • 盘子类
     1 package thread.producer.customer;
     2 
     3 
     4 public class Plate {
     5 
     6     //如果是0,表示盘子内没东西
     7     private int index;
     8     private volatile boolean foodIsFinish = false;
     9     
    10     /**
    11      * 向盘子内添加食物,生产者添加食物时,消费者是不能吃食物的,小心被烫到,哈哈
    12      * @param food
    13      */
    14     public synchronized void addFood(Food food) {
    15         index++;
    16         System.out.println("盘子内增加了" + food.getName());
    17         notifyAll();
    18     }
    19     
    20     public synchronized void eatFood(String chihuo) throws InterruptedException{
    21         //盘子中没有食物,不代表生产者已经将食物生产完,所以此处要判断生产者是否将食物生产完
    22         //只有在盘子没有食物,同时生产者生产完所有食物的时候,该线程才什么都不做,直到线程结束
    23         while(index == 0 && !foodIsFinish) {
    24 //            System.out.println(chihuo + "在等待食物");
    25             wait();
    26         }
    27         if(index > 0) {
    28             index--;
    29             System.out.println("盘子内被"+chihuo+"吃掉");
    30         }
    31     }
    32     
    33     public synchronized boolean isEmpty() {
    34         return index == 0;
    35     }
    36     
    37     public synchronized void setFoodIsFinish(){
    38         this.foodIsFinish = true;
    39     }
    40     
    41     public synchronized boolean getFoodIsFinish() {
    42         return foodIsFinish;
    43     }
    44     /**
    45      * 等待生产者线程执行完毕,该方法不能为同步方法
    46      * @param threads
    47      * @throws InterruptedException
    48      */
    49     public void waitProducerFinish(Thread producerThread) throws InterruptedException {
    50         producerThread.join();
    51         System.out.println("生产者生产食物完毕");
    52         //每个线程结束后,唤醒其他线程,因为有可能出现生产者线程执行完毕,而消费者线程在等待状态,这样就会出现消费者线程一直处于等待状态
    53         //这里只能用同步代码块,不能将整个方法进行同步
    54         synchronized(this) {
    55             setFoodIsFinish();
    56             //notify,notifyAll方法必须在同步方法或同步代码块内,wait方法也一样
    57             notifyAll();
    58         }
    59     }
    60     
    61     /**
    62      * 该方法不能为同步方法
    63      * @param threads
    64      * @throws InterruptedException
    65      */
    66     public void waitCustomerFinish(Thread[] threads) throws InterruptedException {
    67         for(int i = 0; i < threads.length; i++) {
    68             threads[i].join();
    69         }
    70         System.out.println("消费者线程结束");
    71     }
    72 }
    • 消费者线程
     1 package thread.producer.customer;
     2 
     3 public class CustomerThread implements Runnable{
     4     
     5     private Plate plate;
     6     private String chihuo;
     7     
     8     public CustomerThread(Plate plate, String chihuo) {
     9         this.plate = plate;
    10         this.chihuo = chihuo;
    11     }
    12 
    13     @Override
    14     public void run() {
    15         try {
    16             //判断盘子是否为空以及生产者是否已经生产食物完毕
    17             //只要在盘子为空或者生产者还有食物生产时,才不跳出循环
    18             //这样判断是防止生产者还有食物生产,恰好盘子中无食物,线程退出的不正确情况出现
    19             while(!plate.isEmpty() || !plate.getFoodIsFinish()) {
    20 //                System.out.println(chihuo + "准备吃食物");
    21                 plate.eatFood(chihuo);
    22             }
    23         } catch (InterruptedException e) {
    24             e.printStackTrace();
    25         }
    26     }
    27 
    28 }
    View Code
    • 生产者线程
     1 package thread.producer.customer;
     2 
     3 public class ProducerThread implements Runnable{
     4     
     5     private Plate plate;
     6     
     7     public ProducerThread(Plate plate){
     8         this.plate = plate;
     9     }
    10 
    11     @Override
    12     public void run() {
    13         String[] foodType = {"apple","banana","pear","plum","grape","drumstick","hamburg","pineapple","staswberry","orange"};
    14         for(int i = 0; i < 100; i++) {
    15             int random = (int) (Math.random() * 10);
    16             Food food = new Food();
    17             food.setName(foodType[random]);
    18 //            System.out.println("生产者准备添加食物");
    19             plate.addFood(food);
    20         }
    21     }
    22 }
    View Code
    • 测试类
     1 package thread.producer.customer;
     2 
     3 public class Test {
     4 
     5     public static void main(String[] args) {
     6         Plate plate = new Plate();
     7         Thread t1 = new Thread(new ProducerThread(plate));
     8         Thread t2 = new Thread(new CustomerThread(plate, "吃货1号"));
     9         Thread t3 = new Thread(new CustomerThread(plate, "吃货2号"));
    10         t1.start();
    11         t2.start();
    12         t3.start();
    13         Thread[] threads = new Thread[2];
    14         threads[0] = t2;
    15         threads[1] = t3;
    16         try {
    17             plate.waitProducerFinish(t1);
    18             plate.waitCustomerFinish(threads);
    19         } catch (InterruptedException e) {
    20             e.printStackTrace();
    21         }
    22     }
    23 
    24 }
    View Code
  • 相关阅读:
    UICollectionView中使用 UICollectionViewFlowLayout进行布局(模仿苹果相册)
    使用CocoaPods被卡住:Updating local specs repositories
    【原】iOS 同时重写setter和getter时候报错:Use of undeclared identifier '_name';did you mean 'name'
    iOS 设置不同的字体颜色
    使用java代码,动态给TextView设置drawable
    格式化浮点数(保留指定位数)
    监听输入法的出现和隐藏
    dp和px的转换
    获取状态栏高度
    获取在attr.xml中声明的主题样式
  • 原文地址:https://www.cnblogs.com/yuyuj/p/4524148.html
Copyright © 2011-2022 走看看