浅谈多线程生产者与消费者

在我们进行项目开发时我们需要程序同时运行不同的功能代码,也就是所说的不同任务,这时我们会考虑使用线程进行实现。最经典的例子莫属生产者与消费者模式线程开发。

本人简单实现代码如下:

package com.cai;
public class productDemo {
 public static void main(String[] args) {
  Resource r = new Resource();
  productor p1 = new productor(r); 
  Consumer c1= new Consumer(r); 
  Thread t1 = new Thread(p1);
  Thread t2 = new Thread(p1);
  Thread t3 = new Thread(c1);
  Thread t4 = new Thread(c1);
  t1.start();
  t2.start();
  t3.start();
  t4.start();
 }
 
}
class Resource{
 private String name;
 private int count = 1;
 private boolean flag = false;
 public synchronized void setName(String name){
  while(flag){
   try {
    this.wait();
   } catch (InterruptedException e) {    
    e.printStackTrace();
   }   
  }
  this.name=name+count;
  count++;
  System.out.println(Thread.currentThread().getName()+"...生产者..."+this.name);
  flag = true;
  notifyAll();
 }
 public synchronized  void output(){
  while(!flag){
   try {
    this.wait();
   } catch (InterruptedException e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
   }
  }
  System.err.println(Thread.currentThread().getName()+"...消费者........"+this.name);
  flag = false;
  notifyAll();
 }
}

class productor implements Runnable{
    private Resource r;
    public productor(Resource r){
     this.r=r;
    }
 public void run() {
  while(true){
   r.setName("java");
  }
  
 }
 
}
class Consumer  implements Runnable{
    private Resource r;
    Consumer(Resource r){
     this.r=r;
    }
 public void run() {
  while(true){
   r.output();
  }
  
 }
 
}

执行效果如下:

浅谈多线程生产者与消费者


简单解析:

  这里我们要注意一些问题在我们判断线程标志时我们使用while是为了防止生产者生产了几个而消费者未进行消费,原因是如果我们生产者线程1,线程2分别等待,消费者进行唤醒后,生产者线程1获取锁执行后生产了一个,此时标志改为true,那么生产者线程2此时获取了cpu执行权,接着向下执行又生产了一个,生产者线程1此时获取cpu执行权得到标志进行等待,消费者线程1获取执行权判断条件false向下进行执行消费,标志为false此时可能唤醒生产者消费2,标志位false,向下生产,又产生了一个一次分析可知,生产者生产几个而消费者只消费了1个显然不满足生产一个消费一个的需求。在此时我们使用while来进行标志判断,等待之后进行标志获取,此时以上面的进行推理可能形成一个线程死锁,那么此时我们就应该在生产或消费之后来唤醒所有的线程,这样我们的需求才得以满足。

if判断标记,只有一次,会导致不该运行的线程运行了。出现了数据错误的情况。
while判断标记,解决了线程获取执行权后,是否要运行!
notify:只能唤醒一个线程,如果本方唤醒了本方,没有意义。而且while判断标记+notify会导致死锁。
notifyAll解决了本方线程一定会唤醒对方线程的问题。