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

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

© 左建飞 中级黑马   /  2012-8-4 19:20  /  2143 人查看  /  12 人回复  /   0 人收藏 转载请遵从CC协议 禁止商业使用本文

  1. public class InterruptDemo {

  2.         /**
  3.          * @param args
  4.          */
  5.         public static void main(String[] args)
  6.         {
  7.                 StopThread st=new StopThread();
  8.                 Thread t1=new Thread(st);
  9.                 Thread t2=new Thread(st);
  10.                 t1.start();
  11.                 t2.start();
  12.                 //int num=0;
  13.                 //while(true)
  14.                 //{
  15.                         //if(num++==60)
  16.                         //{
  17.                                 t1.interrupt();
  18.                                 t2.interrupt();
  19.                                 //break;
  20.                         //}
  21.                         //System.out.println(Thread.currentThread().getName()+"...."+num);
  22.                 //}       
  23.         }
  24. }
  25. class StopThread implements Runnable
  26. {
  27.         private boolean flag=true;
  28.         public synchronized void run()
  29.         {
  30.                 while(flag)
  31.                 {
  32.                         try
  33.                         {
  34.                                 wait();
  35.                         }
  36.                         catch(InterruptedException e)
  37.                         {
  38.                                 System.out.println(Thread.currentThread().getName()+"...Exception");
  39.                                 flag=false;
  40.                         }
  41.                         System.out.println(Thread.currentThread().getName()+"...run");
  42.                 }
  43.         }
  44. }
复制代码
为什么打印结果只有
Thread-0...ExceptionThread-0...run
呢?两个线程都调用了Interrupt()呀?
加上循环后又有了
Thread-1...ExceptionThread-1...run?


12 个回复

倒序浏览
  1. class InterruptDemo
  2. {
  3.         public static void main(String[] args)
  4.         {
  5.                 StopThread st=new StopThread();
  6.                 Thread t1=new Thread(st);
  7.                 Thread t2=new Thread(st);
  8.                 t1.start();
  9.                 t2.start();
  10.                 t1.interrupt();
  11.                 t2.interrupt();

  12.         }
  13. }
  14. class StopThread implements Runnable
  15. {
  16.         private boolean flag=true;
  17.         public synchronized void run()

  18.         {
  19.                 while(flag)
  20.                 {
  21.                         try
  22.                         {
  23.                                 wait();
  24.                         }
  25.                         catch(InterruptedException e)
  26.                         {
  27.                                 System.out.println(Thread.currentThread().getName()+"...Exception");                              
  28.                                  flag=false;[color=Red]Thread-0被强制清除冻结状态后,打印了Thread-0...Exception,然后把标记改为了false,在往下打印了Thread-0...run。至此因为标记被改变,程序就结束了。所以没有后来的了[/color]
  29.                         }
  30.                         System.out.println(Thread.currentThread().getName()+"...run");
  31.                 }
  32.         }
  33. }
复制代码
回复 使用道具 举报
本帖最后由 芦曦 于 2012-8-5 01:18 编辑
复制代码
回复 使用道具 举报
首先要说wait
线程在执行wait的时候实际是放弃同步操作的
也就是说你一waitThread0,Thread1就有权利执行同步代码块的内容了
在进行t2.interrupt();的时候理应发生异常导致Thread1线程唤醒并打印出
Thread-1...ExceptionThread-1...run?
但是问题出在你调用t2.start()的时候
Thread1还没来得及执行wait就被执行了t2.interrupt();
此时便不会抛出异常,就不会打印Thread-1...Exception
同时由于Thread0抛异常时修改了循环标志
也不会打印Thread-1...run
这种情况不光会出现而且出现的几率相当高
有两种方法可以证明这一点
第一:加延迟,其实你的那60次循环就相当于加延迟
第二:多线程,你多生成几个线程让他们同时启动,并都调用interrupt();多运行几次
这时你就会发现多个线程里面
有几个线程有时得不到运行
但是有时候又会运行
而且你可以在run方法内的while循环内外前后都设置一个打印语句
这样你就可以轻松看见每个线程的运行顺序和运行轨迹了。。。
希望对你能有所帮助。。。
对于线程总会有很多不可思议的地方
因为线程的执行本身就是随机的,不是顺序执行
回复 使用道具 举报
public class InterruptDemo {

        /**

         * @param args

         */

        public static void main(String[] args)

        {

                StopThread st=new StopThread();

                Thread t1=new Thread(st);

                Thread t2=new Thread(st);

                t1.start();//t1等待

                t2.start();//t2等待

                //int num=0;

                //while(true)

                //{

                        //if(num++==60)

                        //{

                                t1.interrupt();//t1被强制唤醒并重新判断while(flag),flag=true,所以往下执行catch(){},flag变为false。

                                t2.interrupt();//t1被强制唤醒并重新判断while(flag),flag=false,所以就不会再往下了。在while语句中,线程被唤醒后都会重新判断条件,如果为真就往下执行while语句,如果假就不会了。if语句中,线程被唤醒后就会直接往下执行。如果把while(flag)改成if(flag),Thread-1...ExceptionThread-1...run也会出现的。

                                //break;

                        //}

                        //System.out.println(Thread.currentThread().getName()+"...."+num);

                //}        
        }

}

class StopThread implements Runnable

{

        private boolean flag=true;

        public synchronized void run()

        {

                while(flag)

                {

                        try

                        {

                                wait();

                        }

                        catch(InterruptedException e)

                        {

                                System.out.println(Thread.currentThread().getName()+"...Exception");

                                flag=false;

                        }

                        System.out.println(Thread.currentThread().getName()+"...run");

                }

        }

}
回复 使用道具 举报
叶征东 发表于 2012-8-5 12:20
public class InterruptDemo {

        /**

同学这个为什么只有Thread-0我懂了,为什么将interrupt语句的上下的注释的语句去掉后,就能打印出Thread-1了呢?
回复 使用道具 举报
侯宪博 发表于 2012-8-5 01:26
首先要说wait
线程在执行wait的时候实际是放弃同步操作的
也就是说你一waitThread0,Thread1就有权利执行同 ...

同学这个为什么只有Thread-0我懂了,为什么将interrupt语句的上下的注释的语句去掉后,就能打印出Thread-1了呢?
回复 使用道具 举报
左建飞 发表于 2012-8-5 18:12
同学这个为什么只有Thread-0我懂了,为什么将interrupt语句的上下的注释的语句去掉后,就能打印出Thread- ...

童鞋,你回复我这句话证明你没好好看我给你的回复。。。你注释的是单纯的60次循环,在循环的过程中Thread1得到了锁并执行了wait。。。
回复 使用道具 举报
侯宪博 发表于 2012-8-5 18:51
童鞋,你回复我这句话证明你没好好看我给你的回复。。。你注释的是单纯的60次循环,在循环的过程中Thread ...

童鞋。我错了。嗯。我又认认真真的看了一遍你的回复。为了证明我看了,我复述你的回复如下:
加了延迟,Thread-0、Thread-1、都有更大的机会执行wait();而不加延迟可能俩线程有一个线程没有执行wait(),从而导致了一个线程打印不出。
但是,同学,我还是笨的不懂,不是执行了一个线程后,flag就被置为false了么?那么就应该只打印一个呀。那么不就结束了么?为什么会打印俩了?
回复 使用道具 举报
左建飞 发表于 2012-8-5 19:29
童鞋。我错了。嗯。我又认认真真的看了一遍你的回复。为了证明我看了,我复述你的回复如下:
加了延迟,T ...

这次问到点子上了,其实在线程0wait的时候他就已经放弃锁了
所以当线程1得到锁以后就会进去执行,执行到wait,线程1也wait了
就都放弃了锁
但是,当线程0和线程1执行interrupt();的时候都是等待状态就都会发生InterruptedException异常
然后就会执行catch语句块接着顺序执行
执行catch语句就会打印Thread-0...Exception和read-1...Exception
接着顺序执行就会打印Thread-0...run和Thread-1...run
也就是说flag虽说已经false了,异常处理是直接就跳进去的
不信你在run方法里while语句内外前后多加几个输出语句你就知道了
你小子还是没把我的回复理解透啊。。。
希望你在多试几遍,
至于异常为什么直接往里跳,那就是异常的知识了
你再查查资料好不。。。
继续加油哈。。。
回复 使用道具 举报
侯宪博 发表于 2012-8-5 20:12
这次问到点子上了,其实在线程0wait的时候他就已经放弃锁了
所以当线程1得到锁以后就会进去执行,执行到w ...

完全懂了。哥们威武。
加延迟,俩个都执行到了wait(),虽然执行了t1.interrupt()后flag变成了false,但是不影响t2.interrupt()。因为t2的wait()已经执行到了。
不加延迟,俩个线程中有可能因为还没执行到wait(),但是主线程已经执行到了interrupt而没有执行异常。而导致了只打印了一个异常的错误。
是这个意思么?
回复 使用道具 举报
左建飞 发表于 2012-8-5 21:25
完全懂了。哥们威武。
加延迟,俩个都执行到了wait(),虽然执行了t1.interrupt()后flag变成了false,但是 ...

看你骨骼清奇,维护世界和平的重任就交给你了。呵呵。。。哥们你中了。。。希望我的回答带给你些许帮助。。。:lol
回复 使用道具 举报
问题已解决!
回复 使用道具 举报
您需要登录后才可以回帖 登录 | 加入黑马