黑马程序员技术交流社区

标题: 多线程问题(生产者消费者)-----生产与消费逻辑错误 [打印本页]

作者: HM赵磊    时间: 2013-3-11 15:45
标题: 多线程问题(生产者消费者)-----生产与消费逻辑错误
class Resource
{
private String name;
private int num=1;
private boolean flag=false;
public synchronized void set(String name)
{
  this.name=(name+"....."+(num++));
  if(flag)
   try
   {
    this.wait();
   }
   catch (Exception e)
   {
    e.printStackTrace();
   }
  System.out.println(Thread.currentThread().getName()+"........."+"生产者"+"..."+this.name);
  this.flag=true;
  this.notify();
}
public synchronized void get()
{
  if(!flag)
   try
   {
    this.wait();
   }
   catch (Exception e)
   {
    e.printStackTrace();
   }
  System.out.println(Thread.currentThread().getName()+"..."+"消费者"+"..."+this.name);
  this.flag=false;
  this.notify();
}
}
class Producer implements Runnable
{
private Resource r;
Producer(Resource r)
{
  this.r=r;
}
public void run()
{
  while(true)   
  {
   r.set("商品");
  }
}
}
class Consumer implements Runnable
{
private Resource r;
Consumer(Resource r)
{
  this.r=r;
}
public void run()
{
  while(true)   
  {
   r.get();
  }
}
}
class ProducerConsumerTest2
{
public static void main(String[] args)
{
  
  Resource r=new Resource();
  Producer pro=new Producer(r);
  Consumer con=new Consumer(r);
  Thread t1=new Thread(pro);
  Thread t2=new Thread(con);
  t1.start();
  t2.start();
}
}

结果是如下,问题出现在哪里?
file:///C:/Documents%20and%20Settings/Administrator/Application%20Data/Tencent/Users/452953881/QQ/WinTemp/RichOle/)U]X61B@D7]JC9OH%7D%7DAU0AI.jpg


作者: HM李超    时间: 2013-3-11 16:07
  1. class Resource
  2. {
  3.         private String name;
  4.         private int num=1;
  5.         private boolean flag=false;
  6.         public synchronized void set(String name)
  7.         {
  8.                 this.name=(name+"....."+(num++));
  9.                   while(flag)
  10.                    try
  11.                    {
  12.                                 this.wait();
  13.                    }
  14.                    catch (Exception e)
  15.                    {
  16.                                 e.printStackTrace();
  17.                    }
  18.                  System.out.println(Thread.currentThread().getName()+"........."+"生产者"+"..."+this.name);
  19.                   this.flag=true;
  20.                   this.notify();
  21.         }
  22.         public synchronized void get()
  23.         {
  24.                   while(!flag)
  25.                            try
  26.                            {
  27.                                 this.wait();
  28.                            }
  29.                            catch (Exception e)
  30.                            {
  31.                                 e.printStackTrace();
  32.                            }
  33.                   System.out.println(Thread.currentThread().getName()+"..."+"消费者"+"..."+this.name);
  34.                   this.flag=false;
  35.                   this.notify();
  36.         }
  37. }
  38. class Producer implements Runnable
  39. {
  40.         private Resource r;
  41.         Producer(Resource r)
  42.         {
  43.           this.r=r;
  44.         }
  45.         public void run()
  46.         {
  47.           while(true)   
  48.           {
  49.                 r.set("商品");
  50.           }
  51.         }
  52. }
  53. class Consumer implements Runnable
  54. {
  55.         private Resource r;
  56.         Consumer(Resource r)
  57.         {
  58.           this.r=r;
  59.         }
  60.         public void run()
  61.         {
  62.           while(true)   
  63.           {
  64.            r.get();
  65.           }
  66.         }
  67. }
  68. class ProducerConsumerTest2
  69. {
  70.         public static void main(String[] args)
  71.         {
  72.           
  73.                   Resource r=new Resource();
  74.                   Producer pro=new Producer(r);
  75.                   Consumer con=new Consumer(r);
  76.                   Thread t1=new Thread(pro);
  77.                   Thread t2=new Thread(con);
  78.                   t1.start();
  79.                   t2.start();
  80.         }
  81. }
复制代码
以上代码可以作为参考,你运行试试看,只要将 Resource类的判断flag标记的if改成while就可以了,
希望可以帮到你
作者: 爪哇攻城狮    时间: 2013-3-11 19:00

  1. class ProducerConsumerDemo
  2. {
  3.         public static void main(String[] args)
  4.         {
  5.                 Resource r = new Resource();

  6.                 Producer pro = new Producer(r);
  7.                 Consumer con = new Consumer(r);

  8.                 Thread t1 = new Thread(pro);
  9.                 Thread t2 = new Thread(pro);
  10.                 Thread t3 = new Thread(con);
  11.                 Thread t4 = new Thread(con);

  12.                 t1.start();
  13.                 t2.start();
  14.                 t3.start();
  15.                 t4.start();

  16.         }
  17. }

  18. /*
  19. 对于多个生产者和消费者。
  20. 为什么要定义while判断标记。
  21. 原因:让被唤醒的线程再一次判断标记。


  22. 为什么定义notifyAll,
  23. 因为需要唤醒对方线程。
  24. 因为只用notify,容易出现只唤醒本方线程的情况。导致程序中的所有线程都等待。

  25. */


  26. class Resource
  27. {
  28.         private String name;
  29.         private int count = 1;
  30.         private boolean flag = false;
  31.                         //  t1    t2
  32.         public synchronized void set(String name)
  33.         {
  34.                 while(flag)
  35.                         try{this.wait();}catch(Exception e){}//t1(放弃资格)  t2(获取资格)
  36.                 this.name = name+"--"+count++;

  37.                 System.out.println(Thread.currentThread().getName()+"...生产者.."+this.name);
  38.                 flag = true;
  39.                 this.notifyAll();
  40.         }


  41.         //  t3   t4  
  42.         public synchronized void out()
  43.         {
  44.                 while(!flag)
  45.                         try{wait();}catch(Exception e){}//t3(放弃资格) t4(放弃资格)
  46.                 System.out.println(Thread.currentThread().getName()+"...消费者........."+this.name);
  47.                 flag = false;
  48.                 this.notifyAll();
  49.         }
  50. }

  51. class Producer implements Runnable
  52. {
  53.         private Resource res;

  54.         Producer(Resource res)
  55.         {
  56.                 this.res = res;
  57.         }
  58.         public void run()
  59.         {
  60.                 while(true)
  61.                 {
  62.                         res.set("+商品+");
  63.                 }
  64.         }
  65. }

  66. class Consumer implements Runnable
  67. {
  68.         private Resource res;

  69.         Consumer(Resource res)
  70.         {
  71.                 this.res = res;
  72.         }
  73.         public void run()
  74.         {
  75.                 while(true)
  76.                 {
  77.                         res.out();
  78.                 }
  79.         }
  80. }
复制代码

作者: 张晋瑜    时间: 2013-3-11 22:32
嗯,确实,必须是个循环
以下是我以前写的:
  1. package synchronous;
  2. /**
  3. * 生产者与消费者问题
  4. * 分析
  5. * 仓库类Warehouse   生产者类Producer   消费者类Consumer
  6. * 临界资源->仓库类Warehouse  临界区->存取产品的动作(代码)
  7. * @author jin
  8. *
  9. */
  10. public class ProducerConsumer {

  11.         /**
  12.          * @param args
  13.          */
  14.         public static void main(String[] args) {
  15.                 // TODO Auto-generated method stub
  16.                 WareHouse buffer=new WareHouse();
  17.                 (new Producer(buffer)).start();
  18.                 (new Consumer(buffer)).start();
  19.         }

  20. }
  21. class WareHouse{
  22.         private int product;        // 仓库中的产品
  23.         private boolean isEmpty=true;        // 标记仓库是否为空
  24.         public void put(int product_put){        //向仓库放入产品
  25.                 // 若仓库不为空,则进入等待状态;
  26.                 while(!isEmpty){
  27.                         try {
  28.                                 wait();
  29.                         } catch (InterruptedException e) {
  30.                                 // TODO Auto-generated catch block
  31.                                 e.printStackTrace();
  32.                         }
  33.                 }
  34.                 // 若为空,则向仓库放入产品(放入了产品当能就要标记仓库不为空咯)并发出通知
  35.                 this.product=product_put;
  36.                 this.isEmpty=false;
  37.                 notify();
  38.         }
  39.         public int get(){        //从仓库取出产品
  40.                 // 若仓库为空,取产品这个动作的线程自然要进入等待状态了
  41.                 while(isEmpty){
  42.                         try {
  43.                                 wait();
  44.                         } catch (InterruptedException e) {
  45.                                 // TODO Auto-generated catch block
  46.                                 e.printStackTrace();
  47.                         }
  48.                 }
  49.                 // 若仓库不为空,返回产品(取出了产品仓库就空了,就要标记仓库为空)并发出通知
  50.                 isEmpty=true;
  51.                 notify();
  52.                 return this.product;
  53.         }
  54. }
  55. class Producer extends Thread{
  56.         private WareHouse buffer;        // 将要访问的临界资源
  57.         public Producer(WareHouse buffer) {
  58.                 // TODO Auto-generated constructor stub
  59.                 this.buffer=buffer;
  60.         }
  61.        
  62.         @Override
  63.         public void run() {
  64.                 // TODO Auto-generated method stub
  65.                 synchronized (buffer) {
  66.                         for(int i=1; i<=5; i++){        // 假设生产5个产品:1、2、3、4、5
  67.                                 buffer.put(i);
  68.                                 System.out.println("存入产品:"+i);
  69.                         }
  70.                 }
  71.         }
  72. }

  73. class Consumer extends Thread{
  74.         private WareHouse buffer;        // 将要访问的临界资源
  75.         public Consumer(WareHouse buffer) {
  76.                 // TODO Auto-generated constructor stub
  77.                 this.buffer=buffer;
  78.         }
  79.        
  80.         @Override
  81.         public void run() {
  82.                 // TODO Auto-generated method stub
  83.                 synchronized (buffer) {
  84.                         for(int i=1; i<=5; i++){        // 生产了5个产品,我们也就5次去拿产品
  85.                                 System.out.println("取出产品:"+buffer.get());
  86.                         }
  87.                 }
  88.         }
  89. }
复制代码





欢迎光临 黑马程序员技术交流社区 (http://bbs.itheima.com/) 黑马程序员IT技术论坛 X3.2