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

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

© ℃葫芦 中级黑马   /  2015-8-12 20:48  /  1228 人查看  /  7 人回复  /   0 人收藏 转载请遵从CC协议 禁止商业使用本文

本帖最后由 ℃葫芦 于 2015-8-12 22:43 编辑

刚才在论坛里跟他们有了不同意见,
我看的是毕向东的视频里面讲的是随机唤醒一条冻结的线程,
其他童鞋都说是唤醒等待最久的一条,我觉得不是,
求大神解答

7 个回复

倒序浏览

  1. /*
  2. 生产者,消费者。

  3. 多生产者,多消费者的问题。
  4. if判断标记,只有一次,会导致不该运行的线程运行了。出现了数据错误的情况。
  5. while判断标记,解决了线程获取执行权后,是否要运行!

  6. notify:只能唤醒一个线程,如果本方唤醒了本方,没有意义。而且while判断标记+notify会导致死锁。
  7. notifyAll解决了本方线程一定会唤醒对方线程的问题。


  8. */

  9. class Resource
  10. {
  11.         private String name;
  12.         private int count = 1;
  13.         private boolean flag = false;
  14.         public synchronized void set(String name)//  
  15.         {
  16.                 while(flag)
  17.                         try{this.wait();}catch(InterruptedException e){}//   t1    t0
  18.                
  19.                 this.name = name + count;//烤鸭1  烤鸭2  烤鸭3
  20.                 count++;//2 3 4
  21.                 System.out.println(Thread.currentThread().getName()+"...生产者..."+this.name);//生产烤鸭1 生产烤鸭2 生产烤鸭3
  22.                 flag = true;
  23.                 notify();
  24.         }

  25.         public synchronized void out()//  t3
  26.         {
  27.                 while(!flag)
  28.                         try{this.wait();}catch(InterruptedException e){}        //t2  t3
  29.                 System.out.println(Thread.currentThread().getName()+"...消费者........"+this.name);//消费烤鸭1
  30.                 flag = false;
  31.                 notify();
  32.         }
  33. }

  34. class Producer implements Runnable
  35. {
  36.         private Resource r;
  37.         Producer(Resource r)
  38.         {
  39.                 this.r = r;
  40.         }
  41.         public void run()
  42.         {
  43.                 while(true)
  44.                 {
  45.                         r.set("烤鸭");
  46.                 }
  47.         }
  48. }

  49. class Consumer implements Runnable
  50. {
  51.         private Resource r;
  52.         Consumer(Resource r)
  53.         {
  54.                 this.r = r;
  55.         }
  56.         public void run()
  57.         {
  58.                 while(true)
  59.                 {
  60.                         r.out();
  61.                 }
  62.         }
  63. }



  64. class  ProducerConsumerDemo
  65. {
  66.         public static void main(String[] args)
  67.         {
  68.                 Resource r = new Resource();
  69.                 Producer pro = new Producer(r);
  70.                 Consumer con = new Consumer(r);

  71.                 Thread t0 = new Thread(pro);
  72.                 Thread t1 = new Thread(pro);
  73.                 Thread t2 = new Thread(con);
  74.                 Thread t3 = new Thread(con);
  75.                 t0.start();
  76.                 t1.start();
  77.                 t2.start();
  78.                 t3.start();

  79.         }
  80. }
复制代码


QQ截图20150812210749.png (63.5 KB, 下载次数: 10)

QQ截图20150812210749.png
回复 使用道具 举报
本帖最后由 ℃葫芦 于 2015-8-12 21:43 编辑

先按照运行0、3、1、3、0结果分析唤醒冻结最久的那条:

0线程运行==》生产烤鸭1==》0线程冻结
下面有两种可能
一种可能是1线程运行,第二种可能是3线程运行,分别说:
可能一:
1线程运行==》判断flog为true==》1线程冻结==》并没有打印任何结果也没唤醒。
3线程运行==》消费烤鸭1==》唤醒冻结最久的0线程==》3线程冻结。
然后下面一个是1线程消费,说明这个可能被否定了。

那么必然是可能二,重新来走一遍
0线程运行==》生产烤鸭1==》0线程冻结
3线程运行==》消费烤鸭1==》唤醒冻结最久的0线程==》3线程冻结。
下面又分两种可能①、2线程运行被冻结;②、1线程运行,2线程未运行,:
①、2线程运行==》2线程判断flog==》2线程冻结(此时未冻结线程只有0、1,根据打印结果,下次运行的是1;冻结的线程按时间算是3>2)
      1线程运行==》1线程生产烤鸭2==》1线程唤醒3线程==》1线程冻结。(此时冻结的线程为2>1)
      3线程运行==》3线程消费烤鸭2==》3线程唤醒2线程==》3线程冻结。(此时冻结线程为1>3)
      0线程运行==》0线程生产烤鸭3==》0线程唤醒1线程==》0线程冻结。(此时冻结线程为3>0)
至此2线程还未被冻结,如果按照此推断,这时应该是2线程消费烤鸭3。

而另一种可能:
②  0线程运行==》生产烤鸭1==》0线程冻结
     3线程运行==》消费烤鸭1==》唤醒冻结最久的0线程==》3线程冻结。
     1线程运行==》生产烤鸭2==》唤醒3线程==》1线程冻结
然后又有两种:2线程运行被冻结;2线程未运行,3线程运行

     3线程运行==》消费烤鸭2==》唤醒1线程==》3线程冻结    0线程运行==》生产烤鸭3==》唤醒3线程==》0线程冻结
可以看到此时3线程未被冻结, 按此理论应该消费烤鸭3!
至此不再判断另一种可能了,因为结果都一样。
所以我坚信!是随机唤醒的。



回复 使用道具 举报
楼上分析得很详细
回复 使用道具 举报
本帖最后由 ℃葫芦 于 2015-8-12 22:05 编辑

而再按照随机的方式,就能解释通了
由于随机唤醒分步太多,就不逐一分析了,下面说具体步骤:
03130
0线程运行==》生产烤鸭1==》0线程冻结
3线程运行==》消费烤鸭1==》唤醒0线程==》3线程冻结。(未冻结线程:0、1、2)
      (此步未打印结果)2线程运行==》2线程判断flog==》2线程冻结(未冻结线程:0、1)
1线程运行==》1线程生产烤鸭2==》1线程唤醒3线程==》1线程冻结。(未冻结线程:0、3)
       (此步未打印结果) 0线程运行==》0线程判断flog==》0线程冻结(未冻结线程:3)
3线程运行==》消费烤鸭2==》唤醒0线程==》3线程冻结(未冻结线程:0)
0线程运行==》生产烤鸭3==》唤醒1线程==》0线程冻结(未冻结线程:1)
       (此步未打印结果)1线程运行==》1线程判断flog==》1线程冻结(全部冻结,死锁)

总结完毕,说的不对请指正。写blog去了~~
回复 使用道具 举报

淼淼兄,看童鞋的名字就是会水的,
不知道童鞋是什么看法啊
回复 使用道具 举报
看不懂      
回复 使用道具 举报
哎  ,折腾死人
回复 使用道具 举报
您需要登录后才可以回帖 登录 | 加入黑马