多线程:生产者消费者(管程法、信号灯法)
2020-06-01 16:12:20来源:博客园 阅读 ()
多线程:生产者消费者(管程法、信号灯法)
1、生产者、消费者
操作系统(生产者、消费者问题)
2、管程法
(1)创建生产者:
public class Productor extends Thread{ SynContainer synContainer; public Productor(SynContainer synContainer){ this.synContainer=synContainer; } public void run(){ for(int i=0;i<10;i++){ synContainer.push(new Chicken(i)); System.out.println("生产了"+i+"只鸡"); } } }
(2)创建消费者:
public class Consume extends Thread { SynContainer synContainer; public Consume(SynContainer synContainer){ this.synContainer=synContainer; } public void run(){ for(int i=0;i<10;i++){ System.out.println("消费了第"+i+"只鸡"); } } }
(3)创建产品类:
public class Chicken { int id; public Chicken(int id) { this.id=id; } }
(4)创建同步代码:
public class SynContainer { Chicken[] chickens=new Chicken[10]; //容器计数器 int count=0; //生产者生产产品 public synchronized void push(Chicken chicken){ //如果容器满了,就需要等待消费的消费 if(count==chickens.length){ //通知消费者消费 try { this.wait(); } catch (InterruptedException e) { e.printStackTrace(); } } //如果没有满就需要丢入产品 chickens[count]=chicken; count++; this.notifyAll(); } public synchronized Chicken pop(){ //判断能否消费 if(count==0){ try { this.wait(); } catch (InterruptedException e) { e.printStackTrace(); } } //如果可以消费,就消费 count--; Chicken chicken=chickens[count]; //吃完了,通知生产者生产 this.notifyAll(); return chicken; } }
保证容器中没有产品的时候生产产品,不能消费;容器中产品满了的时候,不能再去生产产品
(5)创建测试类:
public class Test { public static void main(String[] args) { SynContainer synContainer=new SynContainer(); new Productor(synContainer).start(); new Consume(synContainer).start(); } }
(6)测试:
生产了0只鸡
生产了1只鸡
生产了2只鸡
生产了3只鸡
生产了4只鸡
生产了5只鸡
生产了6只鸡
生产了7只鸡
生产了8只鸡
生产了9只鸡
消费了第0只鸡
消费了第1只鸡
消费了第2只鸡
消费了第3只鸡
消费了第4只鸡
消费了第5只鸡
消费了第6只鸡
消费了第7只鸡
消费了第8只鸡
消费了第9只鸡
3、信号灯法
(1)创建生产者:
//生产者:演员 public class Player extends Thread { TV tv; public Player(TV tv){ this.tv=tv; } public void run(){ for (int i = 0; i < 20; i++) { if(i%2==0){ this.tv.play("猫和老鼠"); }else { this.tv.play("海绵宝宝"); } } } }
(2)创建消费者:
//消费者:观众 public class Watcher extends Thread { TV tv; public Watcher(TV tv){ this.tv=tv; } public void run(){ for (int i = 0; i < 20; i++) { tv.watch(); } } }
(3)书写同步代码:
//产品:节目 public class TV { //演员表演,观众等待 //观众观看,演员等待 String voice;//表演的节目 boolean flag=true; //表演 public synchronized void play(String voice){ if(!flag){ try { this.wait(); } catch (InterruptedException e) { e.printStackTrace(); } } System.out.println("演员表演了:"+voice); //通知观众观看 this.notifyAll();//唤醒 this.voice=voice; this.flag=!this.flag; } //观看 public synchronized void watch(){ if(flag){ try { this.wait(); } catch (InterruptedException e) { e.printStackTrace(); } } System.out.println("观看了"+voice); //通知演员表演 this.notifyAll(); this.flag=!this.flag; } }
(4)创建测试类:
//通过标志位解决 public class Test { public static void main(String[] args) { TV tv=new TV(); new Player(tv).start(); new Watcher(tv).start(); } }
(5)测试:
演员表演了:猫和老鼠
观看了猫和老鼠
演员表演了:海绵宝宝
观看了海绵宝宝
演员表演了:猫和老鼠
观看了猫和老鼠
演员表演了:海绵宝宝
观看了海绵宝宝
演员表演了:猫和老鼠
观看了猫和老鼠
演员表演了:海绵宝宝
观看了海绵宝宝
演员表演了:猫和老鼠
观看了猫和老鼠
演员表演了:海绵宝宝
观看了海绵宝宝
演员表演了:猫和老鼠
观看了猫和老鼠
演员表演了:海绵宝宝
观看了海绵宝宝
演员表演了:猫和老鼠
观看了猫和老鼠
演员表演了:海绵宝宝
观看了海绵宝宝
演员表演了:猫和老鼠
观看了猫和老鼠
演员表演了:海绵宝宝
观看了海绵宝宝
演员表演了:猫和老鼠
观看了猫和老鼠
演员表演了:海绵宝宝
观看了海绵宝宝
演员表演了:猫和老鼠
观看了猫和老鼠
演员表演了:海绵宝宝
观看了海绵宝宝
演员表演了:猫和老鼠
观看了猫和老鼠
演员表演了:海绵宝宝
观看了海绵宝宝
(6)与管程法的最大不同就是,用信号灯法需要设置一个标志位,而管程法是设置一个变量,根据变量的值来进行
原文链接:https://www.cnblogs.com/zhai1997/p/13026704.html
如有疑问请与原作者联系
标签:
版权申明:本站文章部分自网络,如有侵权,请联系:west999com@outlook.com
特别注意:本站所有转载文章言论不代表本站观点,本站所提供的摄影照片,插画,设计作品,如需使用,请与原作者联系,版权归原作者所有
上一篇:JVM 怎么判断对象已经死了?
下一篇:Spring09_动态代理
- 最详细的java多线程教程来了 2020-06-08
- 系统化学习多线程(一) 2020-06-08
- 如何合理地估算线程池大小? 2020-05-31
- 那些面试官必问的JAVA多线程和并发面试题及回答 2020-05-28
- 99 道 Java 多线程面试题,看完我跪了! 2020-05-25
IDC资讯: 主机资讯 注册资讯 托管资讯 vps资讯 网站建设
网站运营: 建站经验 策划盈利 搜索优化 网站推广 免费资源
网络编程: Asp.Net编程 Asp编程 Php编程 Xml编程 Access Mssql Mysql 其它
服务器技术: Web服务器 Ftp服务器 Mail服务器 Dns服务器 安全防护
软件技巧: 其它软件 Word Excel Powerpoint Ghost Vista QQ空间 QQ FlashGet 迅雷
网页制作: FrontPages Dreamweaver Javascript css photoshop fireworks Flash