[Java]多线程之生产者消费者

来源:互联网 发布:如何找淘宝隐藏优惠券 编辑:程序博客网 时间:2024/05/18 00:33

上一篇多线程写完好久了,今天补上顺便回忆下

前面提到死锁的产生,这里来解决下,换个demo

 

购票时会有退票,包子有销售也会有生产,所以提一个实际中的线程问题,经典的生产者消费者

生产者、消费者实现runnable接口,由于双方使用同一个资源包子,可以单独拿出来,写上两个属性,价格和名字

现在生产者要生产包子,相当于给资源--包子的属性赋值,贴上标签,说明这个生产好了,消费者可以拿去。

然后消费者要来拿,此时baozi在生产者里是一个成员变量,如何让消费者拿到?其实就是如何共享数据?让他们使用构造方法传递同一个引用,使用同一个引用就共享了同一个数据。

 

 

接下来,要在run里拿到包子,输出一下

至此生产和消费框架搭建完毕,去demo里启动线程

生产者消费者都是实现接口的方式,这边首先要分别实例化一个对象出来再去启动线程。因为生产者和消费者都是带参的,没有默认的无参了,这边实例化的时候也必须带上

这个时候走起有问题,一直是消费者被调用,但是没有包子

为啥,因为生产者的run方法内一直在new包子,而不是上面的引用传过来的,这样子生产者和消费的包子其实不是同一个,没有实现共享,去掉new这一行

OK~现在依然有问题,因为在生产里,实际上有两步,名字和价格是分开的,这就有可能在命名后被挂起,消费者拿到的是没有价格的包子,或者在有多种包子的时候,出现错乱

再添加一种包子

 

看看运行结果

 

给生产者消费者都上锁,注意锁的选举,必须是同一把锁,这里有现成的对象baozi

再走起,还会出问题,有可能拿到是空的,因为有可能是消费者先走的,这个时候还没有生产。

这个时候同步机制无法解决,他只能解决非原子操作带来的问题,现在就需要进程间通信来搞定~

三个方法,Wait()  Notify()  notifyAll()

怎么实现通知机制的呢,在走到notify的时候,把锁释放掉,另外一个线程就能进来了

他们都在object类下面,虽然线程的实现依赖于thread类,两个线程间如何实现通信的?是因为拥有同一把锁,这一把锁可以是任何一个对象,任何对象都有锁,所以这些具体的通信方法应该是基于顶层的object,而不能局限在thread

 

要解决这种问题:最优的解决方案是:

 * 生产者来说:  看看有没有包子,有的话就等待,没有的话才生产,生产完之后发出通知

 * 消费者来说:  看看有没有包子,有的话就买,没有的话就等待。买了之后就发出通知

 

给包子再加一个属性,flag标志位,默认为false,在生产者里面判断下有没有包子

给生产者和消费者要加上flag,一定要注意,通过flag判断有没有包子必须synchronized()锁里面,否则在判断flag的时候,有可能被挂起,因为这不是原子操作,这会导致后面的进程间通信的几个方法出现异常。

对于消费者来说,有包子才消费,消费了还要通知生产者,生产者还在等待;没有包子就等待

 

对于生产者来说,有包子则等待,等待消费者消费后来的通知;没有包子则生产,生产好了通知消费者有包子了,消费者还在等待

 

OK,走起,至此这个例子基本搞定

 

完整代码:

生产者

public class Producer implements Runnable {    Baozi baozi;int x =0;    public Producer(Baozi b){    baozi = b;    }@Overridepublic void run() {   while(true){ synchronized (baozi) { if(!baozi.flag){   if(x%2==0){baozi.name="天津狗不理";baozi.price=10;}else{baozi.name="澳门猪扒包";baozi.price=20;}   x++;//没有包子,生产,此时就应该有了,改为truebaozi.flag=true; //通知消费者有包子    baozi.notify(); System.out.println("Producer.sell " +baozi.name+"  "+baozi.price); }else{//flag为true,说明有包子,此时要等待消费者来消费try { baozi.wait();} catch (InterruptedException e) {// TODO Auto-generated catch blocke.printStackTrace();} } }   }       }}


消费者

 

public class Customer implements Runnable {    Baozi baozi;public Customer(Baozi b){    baozi = b;    }@Overridepublic void run() { while (true) {  synchronized (baozi) {if(baozi.flag){  System.out.println("Customer got "+ baozi.name+"  "+baozi.price  );  //消费了,置为false  baozi.flag=false;  //给生产者通知,因为你是有才来消费          //而生产者有则是等待,不通知一直等      baozi.notify();}else{try {baozi.wait();} catch (InterruptedException e) {// TODO Auto-generated catch blocke.printStackTrace();}}  } }}}


资源池:

public class Baozi { String name; int    price; boolean flag=false;}


main:

public class MyPandCDemo {public static void main(String[] args) {// TODO Auto-generated method stub        Baozi baozi =new Baozi();//需要带参来实例化Producer producer = new Producer(baozi);Customer customer = new Customer(baozi);Thread thread1 = new Thread(producer, "Producer");Thread thread2 = new Thread(customer, "Customer");thread1.start();thread2.start();}}


 

 

 

0 0
原创粉丝点击