博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
线程通信(生产者消费者问题)、wait()与notify()方法详解
阅读量:7048 次
发布时间:2019-06-28

本文共 3820 字,大约阅读时间需要 12 分钟。

hot3.png

一、线程通信(生产者消费者问题): 

1、线程通讯: 一个线程完成了自己的任务时,要通知另外一个线程去完成另外一个任务。

2、经典问题:生产者与消费者问题。 

1)存在线程安全问题:可能出现价格错乱的情况,所以要加锁,而这里的Product p 对象是唯一的,即可作为锁。

package sram.thread;//产品类class Product{    String name;  //名字    double price;  //价格}//生产者class Producer extends Thread{    Product  p ;    //产品    public Producer(Product p) {        this.p  = p ;    }    public void run(){        int i = 0;        while(true){            synchronized(p){                if(i%2==0){                    p.name = "苹果";                    p.price = 6;                }else{                    p.name = "香蕉";                    p.price = 3;                }                i++;                System.out.println("生产了"+p.name+",单价为"+p.price+"元");            }        }    }}//消费者class Customer extends Thread{    Product p;     public Customer(Product p) {        this.p = p;    }    public void run(){        while(true){            synchronized(p){                System.out.println("消费了"+p.name+"单价为"+p.price+"元");            }        }    }}public class ProAndCust {    public static void main(String[] args){        Product p = new Product();        //创建生产对象        Producer producer = new Producer(p);        //创建消费者        Customer customer = new Customer(p);        //调用start方法开启线程        producer.start();        customer.start();    }}

2)如果我想做到生成一个,消费一个的输出形式该如何做呢? 

所以这里引入,线程中的wait()和notify()方法。

二、wait()与notify()方法详解 

1、改进版生产者消费者问题:

package sram.thread;//产品类class Product{    String name;  //名字    double price;  //价格    boolean flag = false; //产品是否生产完毕的标识,默认情况是没有生产完成。}//生产者class Producer extends Thread{    Product  p ;    //产品    public Producer(Product p) {        this.p  = p ;    }    public void run(){        int i = 0;        while(true){            synchronized(p){                if(p.flag==false){                    if(i%2==0){                        p.name = "苹果";                        p.price = 6;                    }else{                        p.name = "香蕉";                        p.price = 3;                    }                    i++;                    System.out.println("生产了"+p.name+",单价为"+p.price+"元");                    p.flag = true;                    p.notify();//唤醒消费者去消费                }else{                    //已经生产完毕,等待消费者先去消费                    try {                        //生产者等待                        p.wait();                    } catch (InterruptedException e) {                        e.printStackTrace();                    }                }            }        }    }}//消费者class Customer extends Thread{    Product p;     public Customer(Product p) {        this.p = p;    }    public void run(){        while(true){            synchronized(p){                if(p.flag==true){//产品已经生产完毕                    System.out.println("消费了"+p.name+"单价为"+p.price+"元");                    p.flag = false;                    p.notify();//唤醒生产者去生产                }else{                    //产品还没有生产,应该等待生产者先生产。                    try {                        p.wait();//消费者等待                    } catch (InterruptedException e) {                        e.printStackTrace();                    }                }            }        }    }}public class ProAndCust {    public static void main(String[] args){        Product p = new Product();        //创建生产对象        Producer producer = new Producer(p);        //创建消费者        Customer customer = new Customer(p);        //调用start方法开启线程        producer.start();        customer.start();    }}

2、API详解: 

wait(): 等待 如果线程执行了wait方法,那么该线程会进入等待的状态,等待状态下的线程必须要被其他线程调用notify方法才能唤醒。 
notify(): 唤醒 唤醒线程池等待线程其中的一个。 
notifyAll() : 唤醒线程池所有等待线程。

3、wait与notify方法要注意的事项: 

1)wait方法与notify方法是属于Object对象的。 
分析:这两个方法是由锁对象调用的,而所对象可以是任意类型的。 
2)wait方法与notify方法必须要在同步代码块或者是同步函数中才能使用。 
分析:只有同步代码块与同步函数中才会用到锁。 
3)wait方法与notify方法必需要由锁对象调用。 
分析:见图示。

转载于:https://my.oschina.net/u/204616/blog/1587418

你可能感兴趣的文章
解决mysql无法导入本地文件的问题
查看>>
HBase 系统架构
查看>>
RichFace标签学习笔记
查看>>
iOS中block介绍(四)揭开神秘面纱(下)
查看>>
更改yum源为阿里云的yum源
查看>>
解决exchang服务器连接不可用问题
查看>>
Tomcat启动权限
查看>>
一步一步學習partitions之hash partitions
查看>>
POJ 1061 青蛙的约会 扩展欧几里得
查看>>
我的友情链接
查看>>
随笔-ftp文件上传,删除
查看>>
Ansible问题汇总
查看>>
linux上部署hadoop集群 基础篇
查看>>
java中堆(heap)和堆栈(stack)
查看>>
H3C 5500/5820 端口聚合LACP
查看>>
我的友情链接
查看>>
Forefront TMG 服务器中如何规划和实现高可用性
查看>>
Exchange Server 2010 故障分享
查看>>
java正则匹配count字符串
查看>>
Exchange2007/2010如何恢复被禁用或者删除的邮箱
查看>>