线程类Thread的API接口分析系列之interrupt()

来源:互联网 发布:相片合成软件下载 编辑:程序博客网 时间:2024/06/05 20:24

一直对Thread.interrupt()接口不是太清楚,之前以为是直接中止指定线程的接口,后来仔细了解,发现并不是,而是只是在jvm中设置了指定线程的状态值为“中止”,但是并不主动去中止线程,如何处理的权限交给了写线程运行代码的用户。如下面例子

public class ThreadApiTest implementsRunnable {

                   Threadtest = new Thread(new ThreadApiTest());

                   test.start();

                   try{

                            Thread.sleep(10000);

                   }catch (InterruptedException e) {

                            //TODO Auto-generated catch block

                            e.printStackTrace();

                   }

                   test.interrupt();

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

 

         }

         publicvoid run() {

                   //TODO Auto-generated method stub

                   while(true){

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

                            try{

                                     Thread.sleep(1000);

                            }catch (InterruptedException e) {

                                     //TODO Auto-generated catch block

                                     e.printStackTrace();

                            }

                   }

         }

 

}

运行结果:

Thread-0is alive!

Thread-0is alive!

Thread-0is alive!

Thread-0is alive!

mainis end!

java.lang.InterruptedException: sleepinterrupted

Thread-0is alive!

         atjava.lang.Thread.sleep(Native Method)

         atcom.tisson.zrftest.ThreadApiTest.run(ThreadApiTest.java:44)

         atjava.lang.Thread.run(Unknown Source)

Thread-0is alive!

Thread-0is alive!

 

--在主线程调用test.interrupt();并且主线程运行完毕后,test线程并没有如意料中那样终止,而是抛出一个InterruptedException:后继续运行,所以可以确定,interrupt()没有主动终止线程的能力,而是只是设置了改线程的状态为中止。但是当线程在执行object.wait(),Thread.sleep(),Thread.join()属于诸塞状态时时会抛出InterruptedException。除此之外,interrupt()并没有做更多的工作。另外相关的api接口有Thread.currentThread().isInterrupted()和Thread.interrupted(),如果在run的catch 语句块中增加两行代码:

System.out.println(Thread.currentThread().isInterrupted());

System.out.println(Thread.interrupted());

--会发现输出结果是false,false,因为当线程抛出InterruptedException异常后也把线程的中止状态也清理了。另外值得注意的是isInterrupted()是Thread的普通成员方法,interrupted()是Thread的静态成员方法。另外前者只会返回状态而不会清理,后者返回状态的同时进行了清理。源码分析,让我们看看,为什么interrupt()并没有终止线程的能力。

private volatile Interruptible blocker;

public void interrupt() {

       if (this != Thread.currentThread())

           checkAccess();

 

        synchronized (blockerLock) {

           Interruptible b = blocker;

           if (b != null) {

                interrupt0();           // Just to set the interrupt flag

                b.interrupt(this);

                return;

           }

       }

       interrupt0();

}

--可以明显看到blocker并没有在Thread类中进行初始化,那么blocker应该还是为null,所以当我们调用interrupt()时并没有满足if (b!= null)的条件,所以并没有执行b.interrupt(this);只是执行了interrupt0();而前者是真正能中断线程的,后者只是设置中止状态(Just to set the interrupt flag),找不到b.interrupt(this)里面的源码,姑且认为它是能通过抛出异常的方式打断线程。也就是说InterruptedException异常并非sleep抛出的,而是interrupt()抛出的,也就是在线程还在阻塞时interrupt()抛出异常打断阻塞,线程运行阻塞后的命令时捕捉到该异常。

0 0
原创粉丝点击