线程笔记2--线程的通信(生产者与消费者案例分析)

来源:互联网 发布:电子教室软件解锁 编辑:程序博客网 时间:2024/06/15 00:23

线程通信

1、线程通信:不同的线程执行不同的任务,如果这些任务有某种关系,线程之间必须能够通信,协调完成工作,线程通信是相互间状态的切换


2、线程通信-waitnotify方法介绍:

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、线程通信-使用LockCondition接口:

waitnotify方法,只能被同步监听锁对象来调用,否则报错IllegalMonitorStateException.

那么现在问题来了,Lock机制根本就没有同步锁了,也就没有自动获取锁和自动释放锁的概念.

因为没有同步锁,所以Lock机制不能调用waitnotify方法.

解决方案: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();}}




阅读全文
0 0
原创粉丝点击