多线程解决生产者与消费者问题
2016-09-03 23:07
435 查看
生产者消费者问题是一个很有名的线程同步问题,以前学操作系统时,没怎么搞懂,直到现在学java学到多线程这一块才搞懂。该问题描述的是两个共享固定大小的缓冲区的线程问题。生产者的主要作用是生成一定量的数据放到缓冲区中,然后重复此过程。与此同时,消费者也在缓冲区消耗这些数据。该问题的关键就是要保证生产者不会在缓冲区满时加入数据,消费者也不会在缓冲区中空时消耗数据.
要解决该问题,就必须让生产者在缓冲区满时休眠(为了简单起见,本例就一个生产者与一个消费者),等到下次消费者消耗缓冲区中的数据的时候,生产者才能被唤醒,开始往缓冲区添加数据。同样,也可以让消费者在缓冲区空时进入休眠,等到生产者往缓冲区添加数据之后,再唤醒消费者。
下面我用java实现一下:
本例的生产者是厨师,消费者是服务员
生产者(厨师)只负责生产(做菜),在线程里面用一个循环,使厨师不停的做菜
消费者(服务员)只负责消费(上菜),在线程里面也用一个循环,使服务员不停的做菜
这个问题的核心就是要解决两个问题:
1、菜名与菜的描述一定要对应。所以要使用同步
2、厨师与服务员的操作不能同时进行。所以要用flag控制线程的等待与唤醒
通过在主类中启动线程运行
要解决该问题,就必须让生产者在缓冲区满时休眠(为了简单起见,本例就一个生产者与一个消费者),等到下次消费者消耗缓冲区中的数据的时候,生产者才能被唤醒,开始往缓冲区添加数据。同样,也可以让消费者在缓冲区空时进入休眠,等到生产者往缓冲区添加数据之后,再唤醒消费者。
下面我用java实现一下:
本例的生产者是厨师,消费者是服务员
生产者(厨师)只负责生产(做菜),在线程里面用一个循环,使厨师不停的做菜
package producer_and_customer; /** * 生产者:厨师做菜 * @author weixian */ public class Product implements Runnable { private Food food; public Product(Food food){ this.food=food; } @Override public void run() { for(int i=0;i<50;i++){ if(i%2==0){ food.setFood("辣椒炒肉","很辣很好吃!"); }else{ food.setFood("鸡蛋干炒肉","有点臭,不好吃!"); } } } }这里我使用一个循环使厨师不停的生产两道菜,由于启用的是线程,没有设置优先级,所有菜名和菜的描述在输出时可能会不对应,所有这里我使用同步方法实现,代码在后面贴出。
消费者(服务员)只负责消费(上菜),在线程里面也用一个循环,使服务员不停的做菜
package producer_and_customer; /** * 消费者:服务员上菜 * @author weixian */ public class Customer implements Runnable{ private Food food; public Customer(Food food){ this.food=food; } @Override public void run() { for(int j=0;j<50;j++){ food.getFood(); } } }这里同生产者厨师一样,输出也有可能不对应,所以也必须使用同步方法,同步方法写在Food类中
package producer_and_customer; public class Food { private String name; private String des; private boolean flag = true; //true 代表可以生产 false代表可以消费 public String getName() { return name; } public void setName(String name) { this.name = name; } public synchronized void setFood(String name,String des){ if(!flag){ try { this.wait(); //进入等待状态,不能生产 } catch (InterruptedException e) { e.printStackTrace(); } } this.setName(name); try { Thread.sleep(500); } catch (InterruptedException e) { e.printStackTrace(); } this.setDes(des); flag = false; //表示可以消费了 this.notify(); //唤醒当前线程 } public String getDes() { return des; } public synchronized void getFood(){ if(flag){ try { this.wait(); } catch (InterruptedException e) { e.printStackTrace(); } } try { Thread.sleep(500); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(this.getName()+":"+this.getDes()); flag = true; //表示可以生产了 this.notify(); //唤醒当前线程 } public void setDes(String des) { this.des = des; } @Override public String toString() { return "Food [name=" + name + ", des=" + des + "]"; } public Food(String name, String des) { super(); this.name = name; this.des = des; } public Food() { super(); } }在Food类中不仅有两个同步方法分别对应生产者与消费者,在其中还定义了一个变量flag,通过这个flag来控制生产者的生产与消费者的消费。因为这两个操作不能同时进行,所以在生产者(厨师)在生产(做菜)的时候,消费者(服务员)不能消费(上菜)。服务员应该等待厨师把才做好,才能上菜。此时服务员等待,等到厨师做好后唤醒服务员上菜,反之亦然。道理就只有一个,两个操作不能同时进行。
这个问题的核心就是要解决两个问题:
1、菜名与菜的描述一定要对应。所以要使用同步
2、厨师与服务员的操作不能同时进行。所以要用flag控制线程的等待与唤醒
通过在主类中启动线程运行
Food food = new Food(); Product product = new Product( food ); Customer customer = new Customer(food); new Thread(product).start(); new Thread(customer).start();运行结果如下:
相关文章推荐
- 多线程_生产者消费者题代码2并解决线程安全问题
- Java多线程之~~~使用Exchanger在线程之间交换数据[这个结合多线程并行会有解决很多问题]生产者消费者模型
- 多线程-生产者消费者问题代码2并解决线程安全问题
- c#多线程之生产者与消费者问题的解决
- NSCondition 多线程解决生产者消费者问题
- java多线程解决生产者消费者问题
- Linux多线程实践(8) --Posix条件变量解决生产者消费者问题
- java 多线程学习之多生产者多消费者产生的线程安全问题分析与解决:Lock和Condition
- 多线程——生产者与消费者(多)问题解决
- 多线程——生产者与消费者(多)1.5新锁,问题解决
- Linux多线程实践(8) --Posix条件变量解决生产者消费者问题
- Linux多线程实践(5) --Posix信号量与互斥量解决生产者消费者问题
- java 多线程 详解 生产者消费者 问题解决
- 29-多线程(线程间通信-多生产者多消费者问题-JDK1.5新特性-Condition).1 2 31-多线程(线程间通信-多生产者多消费者问题-JDK1.5解决办法-范例). 1 2
- Linux多线程实践(8) --Posix条件变量解决生产者消费者问题
- java多线程解决生产者消费者问题
- 多线程(线程间通信-多生产者多消费者问题-JDK1.5解决办法-范例),停止线程,线程中方法的区别,匿名内部类实现多线程,线程总结
- Java多线程解决生产者和消费者问题(面向对象)
- java多线程总结六:经典生产者消费者问题实现
- 用C#多线程解决生产者-消费者问题