A股上市公司传智教育(股票代码 003032)旗下技术交流社区北京昌平校区

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

© 舍我其谁 中级黑马   /  2014-8-10 12:25  /  1752 人查看  /  7 人回复  /   0 人收藏 转载请遵从CC协议 禁止商业使用本文

用if判断标记,不是最多也就生产两次消费一次,或者生产一次,消费两次吗?可我的运行结果怎么会这样?请大神指点
Thread-0 生产者电视机...57327
Thread-1..消费者...电视机...57327
Thread-0 生产者电视机...57328
Thread-3..消费者...电视机...57328
Thread-2 生产者电视机...57329
Thread-0 生产者电视机...57330
Thread-3..消费者...电视机...57330
Thread-1..消费者...电视机...57330
Thread-3..消费者...电视机...57330
Thread-1..消费者...电视机...57330
Thread-0 生产者电视机...57331
Thread-2 生产者电视机...57332
Thread-3..消费者...电视机...57332
Thread-0 生产者电视机...57333
Thread-2 生产者电视机...57334
Thread-0 生产者电视机...57335
Thread-2 生产者电视机...57336
Thread-0 生产者电视机...57337
Thread-2 生产者电视机...57338
Thread-0 生产者电视机...57339
Thread-2 生产者电视机...57340
Thread-0 生产者电视机...57341
Thread-2 生产者电视机...57342
Thread-0 生产者电视机...57343
代码如下:

  1. package MyCode;

  2. public class MyLock {
  3.         public static void main(String[] args) {
  4.                 ChangPin cp=new ChangPin();//商品对象
  5.                 Sheng s=new Sheng(cp);//生产者对象
  6.                 Xiao x=new Xiao(cp);//消费者对象
  7.                 //创建线程
  8.                 Thread t1=new Thread(s);
  9.                 Thread t2=new Thread(x);
  10.                 Thread t3=new Thread(s);
  11.                 Thread t4=new Thread(x);
  12.                 //开启线程
  13.                 t1.start();
  14.                 t2.start();
  15.                 t3.start();
  16.                 t4.start();
  17.                
  18.         }

  19. }

  20. class ChangPin
  21. {
  22.   private String name; //商品名称
  23.   private int count;//次数
  24.   boolean flag=false;//标记
  25.   public synchronized void setName(String name)
  26.   {
  27.                   if(flag)
  28.                   {
  29.                                   try {
  30.                                         this.wait();
  31.                                 } catch (InterruptedException e) {
  32.                                         e.printStackTrace();
  33.                                 }
  34.                   }
  35.                   this.name=name+"..."+count++;
  36.                   System.out.println(Thread.currentThread().getName()+" 生产者"+this.name);
  37.                   flag=true;
  38.                   this.notify();
  39.                   
  40.           
  41.   }  
  42.   
  43.   public synchronized void outName()
  44.   {
  45.           if(!flag)
  46.           {
  47.                           try {
  48.                                 this.wait();
  49.                         } catch (InterruptedException e) {
  50.                                 e.printStackTrace();
  51.                         }
  52.           }
  53.           System.out.println(Thread.currentThread().getName()+"..消费者..."+this.name);
  54.           flag=false;
  55.           this.notify();
  56.   }
  57. }

  58. class Sheng implements Runnable
  59. {
  60.         private ChangPin cp;
  61.         public Sheng(ChangPin cp)
  62.         {
  63.                 this.cp=cp;
  64.         }
  65.        
  66.         public void run()
  67.         {
  68.                 while(true)
  69.                 cp.setName("电视机");
  70.         }
  71. }

  72. class Xiao implements Runnable
  73. {
  74.         private ChangPin cp;
  75.         public Xiao(ChangPin cp)
  76.         {
  77.                 this.cp=cp;
  78.         }
  79.    public void run()
  80.    {
  81.            while(true)
  82.            cp.outName();
  83.    }
  84. }
复制代码

7 个回复

倒序浏览
代码有两个问题:
1.notify() 只唤醒一个。 有可能出现唤醒己方线程的情况 从而造成己方线程全部等到。要换位notifyAll()
2.if判断一次。唤醒己方多次操作。应该换位while。
回复 使用道具 举报
谁说用if最多生产2次消费1次的?线程一旦失去约束,完全可能被执行3次、4次才切换到其他线程
回复 使用道具 举报
一楼说的没错,给你我写的recourse代码参考,用lock写的。
public class Res {
        private String name;
        private String sex;
        private boolean flag=false;
        private Lock lock = new ReentrantLock();
        private Condition condition = lock.newCondition();
        public void Set(String name,String sex) throws InterruptedException{
                lock.lock();
                        try {
                                while(flag)
                                condition.await();
                                this.name = name;
                                this.sex = sex;
                                System.out.println(Thread.currentThread().getName()+"生产者");
                                flag =true;
                                condition.signalAll();
                        }finally{
                                lock.unlock();
                        }
        }
        public void show() throws InterruptedException{
                lock.lock();
                        try {
                                while(!flag)
                                condition.await();
                                System.out.println("名字"+name+"性别"+sex+Thread.currentThread().getName());
                                flag = false;
                                condition.signalAll();
                        }finally{
                                lock.unlock();
                        }
               
        }
}
回复 使用道具 举报
fantacyleo 发表于 2014-8-10 14:00
谁说用if最多生产2次消费1次的?线程一旦失去约束,完全可能被执行3次、4次才切换到其他线程 ...

不是有标记吗?怎么还会失去约束
回复 使用道具 举报
:L楼上都答非所问,楼主请看API文档对notify()方法的说明:唤醒在此对象监视器上等待的单个线程。如果所有线程都在此对象上等待,则会选择唤醒其中一个线程。选择是任意性的,并在对实现做出决定时发生。
看到了吗?选择是任意性的,也就是说最坏最坏的情况下有可能出现10000个生产者才会消费一个
回复 使用道具 举报
舍我其谁 发表于 2014-8-10 17:37
不是有标记吗?怎么还会失去约束

有标记没用啊,唤醒是全部唤醒,你把while改成了if,醒后就不再判断标记直接往下运行
回复 使用道具 举报
dispensable 发表于 2014-8-10 19:14
楼上都答非所问,楼主请看API文档对notify()方法的说明:唤醒在此对象监视器上等待的单个线程。如果所 ...

哦,谢谢,受教了
回复 使用道具 举报
您需要登录后才可以回帖 登录 | 加入黑马