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

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

© 陈雪琪 中级黑马   /  2013-5-3 10:57  /  1668 人查看  /  6 人回复  /   0 人收藏 转载请遵从CC协议 禁止商业使用本文

本帖最后由 陈雪琪 于 2013-5-3 13:10 编辑
  1. class ThisLockDemo
  2. {
  3.         public static void main(String[] args){
  4.                 Ticket t=new Ticket();
  5.                 Thread t1=new Thread(t);
  6.                 Thread t2=new Thread(t);
  7.                 t1.start();
  8.                 try{Thread.sleep(10);}catch(Exception e){}
  9.                 t.flag=false;
  10.                 t2.start();
  11.         }
  12. }
  13. class Ticket implements Runnable
  14. {
  15.         private int num=100;
  16.         Object obj=new Object();
  17.         boolean flag=true;
  18.         public  void run(){
  19.                 if(flag){
  20.                         while(true){
  21.                                 synchronized(obj){
  22.                                         if(num>0){
  23.                                                 try{Thread.sleep(10);}
  24.                                                 catch(InterruptedException e){}
  25.                                                 System.out.println(Thread.currentThread().getName()+"sale.."+num--);
  26.                                         }
  27.                
  28.                                 }
  29.                         }
  30.                 }
  31.                 else
  32.                         while(true)
  33.                                 show();
  34.         }
  35.         
  36.         public synchronized void show(){
  37.                 if(num>0){
  38.                         try{Thread.sleep(10);}
  39.                         catch(InterruptedException e){}
  40.                         System.out.println(Thread.currentThread().getName()+"showshow........"+num--);
  41.                 }
  42.         }
  43.         
  44. }
复制代码
这段代码的运行结果是(只截取了一小部分)

问题:
为什么Thread-0线程一直打印的都是同步代码块中的sale。虽然老师说让主线程睡一会,先不让flag变为false。可是当主线程醒了后flag就会变成false了啊,这个时候Thread-0就应该执行的是同步函数show方法中的内容了,应该要打印showshow才是吧?为什么还是直到最后都是打印sale呢?

PS:刚学到这,现在该程序是不安全的,暂且不纠结程序的安全问题。


捕获.PNG (14.3 KB, 下载次数: 0)

运行结果(截取的是前半部分)

运行结果(截取的是前半部分)

评分

参与人数 1技术分 +1 收起 理由
田磊阳 + 1

查看全部评分

6 个回复

倒序浏览
本帖最后由 曹德君 于 2013-5-3 12:04 编辑

是这样子的,Thread0开启线程 flag为ture ,进如while循环体而他的的条件一直为真,没有跳出循环体。thread1开启后检查flag为false就去运行show了。
  1. class ThisLockDemo
  2. {
  3.         public static void main(String[] args){
  4.                 Ticket t=new Ticket();
  5.                 Thread t1=new Thread(t);
  6.                 Thread t2=new Thread(t);
  7.                 t1.start();
  8.                 try{Thread.sleep(10);}catch(Exception e){}
  9.                 t.flag=false;
  10.                 t2.start();
  11.         }
  12. }
  13. class Ticket implements Runnable
  14. {
  15.         private int num=100;
  16.         Object obj=new Object();
  17.         boolean flag=true;
  18.         public  void run(){
  19.                 if(flag){
  20.                         while(flag){//此处的while循环条件换成flag可以应该可以达到你想要的效果。
  21.                                 synchronized(obj){
  22.                                         if(num>0){
  23.                                                 try{Thread.sleep(10);}
  24.                                                 catch(InterruptedException e){}
  25.                                                 System.out.println(Thread.currentThread().getName()+"sale.."+num--);
  26.                                         }
  27.                
  28.                                 }
  29.                         }
  30.                 }
  31.                 else
  32.                         while(true)
  33.                                 show();
  34.         }
  35.         
  36.         public synchronized void show(){
  37.                 if(num>0){
  38.                         try{Thread.sleep(10);}
  39.                         catch(InterruptedException e){}
  40.                         System.out.println(Thread.currentThread().getName()+"showshow........"+num--);
  41.                 }
  42.         }
  43.         
  44. }
复制代码

评分

参与人数 1技术分 +1 收起 理由
田磊阳 + 1

查看全部评分

回复 使用道具 举报
本帖最后由 黑马华 于 2013-5-3 12:08 编辑

这个你一开始运行的线程t1就去运行run方法了,它一直在内部运行,不会再一次判断flag,所以后面那个flag只会影响线程t2
调用run方法再调用show方法。所以thread0只会显示sale,thread1只会显示showshow
回复 使用道具 举报
因为当Thread0线程开启后,判读flag为ture,进入执行下面的代码块,又因为while的条件一直为true,所以会一直循环执行代码块中的了,所以一直打印的是sale。当Thread1线程开启后,判断flag为false所以会执行同步函数内的内容,而同步函数里还是一个死循环,一直会打印showshow了。而且发现您的同步代码块和同步函数使用的不是同一个锁。
  1. class ThisLockDemo
  2. {
  3.         public static void main(String[] args){
  4.                 Ticket t=new Ticket();
  5.                 Thread t1=new Thread(t);
  6.                 Thread t2=new Thread(t);
  7.                 t1.start();
  8.                 try{Thread.sleep(10);}catch(Exception e){}
  9.                 t.flag=false;
  10.                 t2.start();
  11.         }
  12. }
  13. class Ticket implements Runnable
  14. {
  15.         private int num=100;
  16.         Object obj=new Object();
  17.         boolean flag=true;
  18.         public  void run(){
  19.                 if(flag){
  20.                         while(true){
  21.                                 synchronized(obj){
  22.                                         if(num>0){
  23.                                                 try{Thread.sleep(10);}
  24.                                                 catch(InterruptedException e){}
  25.                                                 System.out.println(Thread.currentThread().getName()+"sale.."+num--);
  26.                                         }
  27.                
  28.                                 }
  29.                         }
  30.                 }
  31.                 else
  32.                         while(true)
  33.                                 show();
  34.         }
  35.         
  36.         public synchronized void show(){
  37.                 if(num>0){
  38.                         try{Thread.sleep(10);}
  39.                         catch(InterruptedException e){}
  40.                         System.out.println(Thread.currentThread().getName()+"showshow........"+num--);
  41.                 }
  42.         }
  43.         
  44. }
复制代码

点评

谢谢指点~~嗯嗯 用的不是同一个锁 当时还没有改的呢。  发表于 2013-5-3 13:21
回复 使用道具 举报
曹德君 发表于 2013-5-3 11:59
是这样子的,Thread0开启线程 flag为ture ,进如while循环体而他的的条件一直为真,没有跳出循环体。thread ...

谢谢咯 终于知道是while循环体没有被跳出的原因。只是你修改代码标出注释的地方好像有点小问题噢  如果我换成flag的话  Thread0线程运行一下后就不运行了   好像是因为while循环为false后,就跳出了循环。只有Thread1线程一直在运行。不知道有没有说错额~~~
回复 使用道具 举报
黑马华 发表于 2013-5-3 12:05
这个你一开始运行的线程t1就去运行run方法了,它一直在内部运行,不会再一次判断flag,所以后面那个flag只 ...

谢谢指点咯~~
回复 使用道具 举报
您需要登录后才可以回帖 登录 | 加入黑马