看这段代码:
很简单, 20000个线程, 名字是thread1 ~ thread10000thread1-sleep ~ thread10000-sleep
每个threadi-sleep会睡1秒钟,同时threadi会中断它。
    public class InterruptTest {
       
        public static void main(String[] args) throws Exception {
            for (int i = 1; i <= 10000; i++) {
                Thread t = new Interrupt();
                t.setName("thread" + i);
                t.start();
            }
        }
       
        private static class Interrupt extends Thread {
            public void run() {
                Thread t = new Sleep();
                t.setName( getName() + "-sleep" );
                t.start();
                t.interrupt();
                System.out.println( System.currentTimeMillis() + " " +
                                    t.getName() + " " + t.isInterrupted() );
            }
        }
       
        private static class Sleep extends Thread {
            public void run() {
                try {
                    Thread.sleep(1000);
                } catch (Exception e) {
                    return;
                }
                System.err.println( System.currentTimeMillis() + " No! " +
                                    getName() + " " + isInterrupted() );
            }
        }
       
    }我以为最后一句System.err.println()不可能被执行到,因为上面的Thread.sleep()肯定会被中断,然后就到了return。但是stderr里却实有输出:
1304393164531 No! thread949-sleep true
1304393164562 No! thread1128-sleep false不是每次运行都发生,好像是偶尔才发生。
可以看到,我在每次interrupt()语句后面,都向stdout输出一行。然后我在stdout里面找到了这两行输出,把它们和上面的输出放在一起看:
1304393163531 thread949-sleep true
1304393164531 No! thread949-sleep true
1304393163562 thread1128-sleep true
1304393164562 No! thread1128-sleep false可以看到,这两个interrupt()语句已经执行完了,而且是在stderr输出的1秒钟前。那么,为什么这两个sleep()没有被中断?P.S. 我在3台电脑上运行了这个程序很多次,3台都是Windows XP。上述情况只在其中两台发生,这两台都是酷睿双核 2.4GHz。在另一台电脑上没有发生,那台是赛扬 1.5GHz。它们的JDK版本都完全相同,都是1.6。

解决方案 »

  1.   

    interrupt执行的时候是需要时间的并不是马上执行。
      

  2.   

    因为本身起那么多线程就非常耗时间, 而且你才sleep1秒,所以很有可能interrupt没有被执行。
      

  3.   

    1、interrupt做的工作只是把一个线程中断状态设置为true,并不中断线程,也就是:如果没啥异常的话,把中断状态设置为true后线程该干啥还是干啥多线程本来就是很随机的,在Interrupt的run方法中用Sleep的一个实例启动一个线程,然后LZ就可以开始想了:
    1、如果此时CPU马上切换,OS将CPU分配给刚刚启动的这个线程,让它休眠大概一秒,然后打印出No! false(为了简单,只列出只要信息),然后切换回来,t.interrupt(),然后打印出t.getName() + true,不过这种情况基本不可能发生,因为那个线程睡眠的时候OS不可能让CPU的闲置的2、如果此时CPU马上切换,OS将CPU分配给刚刚启动的这个线程,让它休眠大概一秒,此时CPU切换回来(上面那种不太可能的情况是:CPU在那不动,并不切换回来),执行t.interrupt(),有可以分两种情况:a、此时t启动的线程还在睡眠(1s还没过去),试图将一个正在睡眠的线程中断状态设置为true,那么t的中断状态就被清掉,也就是isInterrupted()会返回false,然后抛出一个InterruptedException,LZ的处理方法是return,所以打印出t.getName + false b、此时t启动的线程刚刚睡醒,在打印No!那些东西之前CPU回来,t.interrupt()把t的status设置为true,此时又可能因为CPU切换的关系,可能先打印t.getName() + true,也可能No! t.getName()+ true,反正可以随便想~~~如果t启动的线程睡醒后直接打印出执行打印No!的那句,那么因为t的中断状态还没被设定,所以打印No!+t.getName()+false,然后t.interrup()设定t的中断状态,再打印出t.getName() +  true
    大概就是这样,因为没有同步,多线程的结果是无法预测的,要考虑所以情况,而这个常常是很难做到的。
      

  4.   

    可是,我把时间输出来了,你看:
    1304393163562 thread1128-sleep true
    1304393164562 No! thread1128-sleep false前一个输出是在1秒钟以前,所以我觉得这肯定不是您说的情况b,而应该是情况a,所以thread1128-sleep应该被中断,抛出异常。可是为什么它没有?
      

  5.   

    dreamhunter_lan大牛,您能解答一下我4楼的问题吗?
      

  6.   

    因为在调用start()之后,再调用interrupt之前已经花费了1秒以上,所以sleep(1000)正常的结束了。没有被中断
      

  7.   

    问题在于,我把时间输出来了,你看:
    1304393163531 thread949-sleep true
    1304393163562 thread1128-sleep true
    1304393164531 No! thread949-sleep true
    1304393164562 No! thread1128-sleep falseInterrupt语句的时间是在sleep结束1秒之前!
      

  8.   

    同样看不懂这个结果,既然能够到打印No!那一句,就说明一定没有抛出异常,所以不存在它正在睡眠的时候t.interrupt()执行这种情况。我觉得问题出现的println上,你把那些函数拿出来,分别求值后,把它们的值传到println打印。其实最有可能的就是准备打印No!,也就是进入到System.err.println( System.currentTimeMillis() + " No! " + getName() + " " + isInterrupted() );准备计算时间,获得线程名字和线程中断状态(此时还没被设置为true),发生切换了,OS保存现场,切换到其他线程,某个时刻被这个线程又得到机会执行,恢复现场,取时间,取名字,取线程中断状态(OS保存的是被置为true之前的那份,所以还是false),打印出来~~~不知道这算不算是在没有同步情况下对象的状态不一致现象,也就因为这样才需要用volatile关键字??我有点晕了~~哈哈
      

  9.   

    我又试了一遍,把所有println语句都删掉了,然后把sleep时间改成1分钟。
    现的我预期的结果是,程序不可能运行1分钟,因为这些sleep都会被中断。但是结果是,有几次果然运行了1分钟。所以结果和上次是一样的,确实有些sleep没有被中断。
      

  10.   

    我试了一下,和线程的数量正相关。这应该算jvm的一个bug吧。
    for (int i = 1; i <= 10000; i++) {
    Thread t = new Interrupt();
    t.setName("thread" + i);
    t.start();
    Thread.sleep(1);
    }
    我加了一个Thread.sleep(1);问题就不会出现了。
      

  11.   

     t.interrupt();
    System.out.println( System.currentTimeMillis() + " " +t.getName() + " " + t.isInterrupted() );谁能保证, interrupt之后,JVM执行的是ccer