线程笔记2--线程的通信(生产者与消费者案例分析)
来源:互联网 发布:电子教室软件解锁 编辑:程序博客网 时间:2024/06/15 00:23
线程通信
1、线程通信:不同的线程执行不同的任务,如果这些任务有某种关系,线程之间必须能够通信,协调完成工作,线程通信是相互间状态的切换。
2、线程通信-wait和notify方法介绍:
java.lang.Object类提供类两类用于操作线程通信的方法.
wait():执行该方法的线程对象释放同步锁,JVM把该线程存放到等待池中,等待其他的线程唤醒该线程(失去CPU和锁).
notify:执行该方法的线程随机唤醒在等待池中等待的任意一个线程,把线程转到锁池中等待.
notifyAll():执行该方法的线程唤醒在等待池中等待的所有的线程,把线程转到锁池中等待.
!注意:上述方法只能被同步监听锁对象来调用,否则报错IllegalMonitorStateException...
3、生产者与消费者案例分析:
为什么生产者不直接把数据给消费者,而是先把数据存储到共享资源中,然后,消费者再从共享资源中取出数据,再消费.
在这里体现了面向对象的设计理念:低耦合.
高(紧)耦合:直接使用生产者把肉包子给消费者,那么生产者中得存在消费者的引用,同理,消费者要消费生产者生产的肉包子,消费者中也得存在生产者对象的引用.
低(松)耦合:使用一个中间对象,屏蔽了生产者和消费者直接的数据交互.
Demo:
public class ThreadDemo1 {public static void main(String[] args) {Product pro = new Product();Producers ps = new Producers(pro);Salers ss = new Salers(pro);Thread th1 = new Thread(ps);Thread th2 = new Thread(ss);th1.start();th2.start();}}class Product {private int id;private String name;private boolean flag;private int i;public int getId() {return id;}public void setId(int id) {this.id = id;}public String getName() {return name;}public void setName(String name) {this.name = name;}public boolean isFlag() {return flag;}public void setFlag(boolean flag) {this.flag = flag;}//producesynchronized public void produce() {if (this.isFlag()) {try {this.wait();} catch (InterruptedException e) {// TODO Auto-generated catch blocke.printStackTrace();}}this.setName("小火炮");this.setId(++i);System.out.println("produce: "+this.getName()+this.getId());this.setFlag(true);this.notify();}//salesynchronized public void sale() {if (!this.isFlag()) {try {this.wait();} catch (InterruptedException e) {// TODO Auto-generated catch blocke.printStackTrace();}}System.out.println("sale: "+this.getName()+this.getId());this.setFlag(false);this.notify();}}class Producers implements Runnable{private Product pro;public Producers(Product pro) {this.pro = pro;}@Overridepublic void run() {while(true) {pro.produce();}}}class Salers implements Runnable{private Product pro;public Salers(Product pro) {this.pro = pro;}@Overridepublic void run() {while(true) {pro.sale();}}}
4、线程通信-使用Lock和Condition接口:
wait和notify方法,只能被同步监听锁对象来调用,否则报错IllegalMonitorStateException.
那么现在问题来了,Lock机制根本就没有同步锁了,也就没有自动获取锁和自动释放锁的概念.
因为没有同步锁,所以Lock机制不能调用wait和notify方法.
解决方案:Java5中提供了Lock机制的同时提供了处理Lock机制的通信控制的Condition接口.
1):使用Lock机制取代synchronized代码块和synchronized方法.
2):使用Condition接口对象的await,signal,signalAll方法取代Object类中的wait,notify,notifyAll方法.
Demo:
多个生产者和消费者案例:
//产品:public class Product {private String name;private String country;private boolean isEmpty = true;Lock lock = new ReentrantLock();Condition cd_p = lock.newCondition();Condition cd_s = lock.newCondition();public void pro(String n, String c){lock.lock();try {while(!isEmpty){cd_p.await();}name = n;Thread.sleep(10);country = c;isEmpty = false;cd_s.signalAll();} catch (Exception e) {e.printStackTrace();}finally{lock.unlock();}}public void sale(){lock.lock();try {while(isEmpty){cd_s.await();}Thread.sleep(10);System.out.println(this.name+"---"+this.country);isEmpty = true;cd_p.signalAll();} catch (Exception e) {e.printStackTrace();}finally{lock.unlock();}}}//消费者:public class Consumer extends Thread{Product p = null;public Consumer(Product p) {this.p = p;}public void run() {for (int i = 0; i <25; i++) {p.sale();}}}//生产者:public class Producer extends Thread{Product p = null;public Producer(Product p) {this.p = p;}public void run() {for(int i = 0; i <25; i++){if(i%2==0){p.pro("火炮", "中国");}else{p.pro("香肠", "四川");}}}}//测试类public class Test {public static void main(String[] args) {Product p = new Product();new Consumer(p).start();new Consumer(p).start();new Producer(p).start();new Producer(p).start();}}
- 线程笔记2--线程的通信(生产者与消费者案例分析)
- Java SE学习笔记:线程通信、生产者与消费者案例、线程状态(线程的生命周期)、线程操作、Condition类
- 线程--生产者与消费者的案例
- 线程间的通信(生产者与消费者)
- JavaSE 多线程 线程间通信 生产者与消费者案例
- 线程的通信-生产者消费者
- Java线程间通信问题分析(生产者消费者模型)
- JAVA 线程间通信 - 生产者与消费者
- JAVA 线程间通信 - 生产者与消费者
- java线程通信 生产者与消费者模式
- 线程间通信(生产者与消费者问题)
- 线程(消费者与生产者)
- 线程经典案例---(生产者和消费者)
- 线程生产者与消费者
- 线程---生产者与消费者
- 线程通信,生产者消费者问题(Java)
- JAVA线程间通信(生产者消费者)
- 线程间通信-生产者消费者
- 二叉树表示——数组
- 系统服务
- mysql函数-FROM_UNIXTIME
- 201412-2 Z字形扫描
- 假设银行Bank已经有了按整年year计算利息的一般方法,其中year只能取正整数。如: Double computerInterest() { Interest=year*0.35*saveMon
- 线程笔记2--线程的通信(生产者与消费者案例分析)
- 小问题2
- 继承
- arcgis api for javascript 自定义工具栏总结
- centos7系统下挂载磁盘
- 数据结构第十周项目2--用二叉树求解代数表达式
- 机器学习数学|Taylor展开式与拟牛顿
- 【云星数据---Apache Flink实战系列(精品版)】:Apache Flink实战基础006--flink分布式部署001
- Javascript中带参数的构造函数的执行过程