一、Java中断的现象
首先,看看Thread类里的几个方法:
public static boolean interrupted | 测试当前线程是否已经中断。线程的中断状态 由该方法清除。换句话说,如果连续两次调用该方法,则第二次调用将返回 false(在第一次调用已清除了其中断状态之后,且第二次调用检验完中断状态前,当前线程再次中断的情况除外)。 |
public boolean isInterrupted() | 测试线程是否已经中断。线程的中断状态 不受该方法的影响。 |
public void interrupt() | 中断线程。 |
上面列出了与中断有关的几个方法及其行为,可以看到interrupt是中断线程。如果不了解Java的中断机制,这样的一种解释极容易造成误解,认为调用了线程的interrupt方法就一定会中断线程。
其实,Java的中断是一种协作机制。也就是说调用线程对象的interrupt方法并不一定就中断了正在运行的线程,它只是要求线程自己在合适的时机中断自己。每个线程都有一个boolean的中断状态(不一定就是对象的属性,事实上,该状态也确实不是Thread的字段),interrupt方法仅仅只是将该状态置为true
public class TestInterrupt { public static void main(String[] args) { Thread t = new MyThread(); t.start(); t.interrupt(); System.out.println("已调用线程的interrupt方法"); } static class MyThread extends Thread { public void run() { int num = longTimeRunningNonInterruptMethod(2, 0); System.out.println("长时间任务运行结束,num=" + num); System.out.println("线程的中断状态:" + Thread.interrupted()); } private static int longTimeRunningNonInterruptMethod(int count, int initNum) { for(int i=0; i<count; i++) { for(int j=0; j<Integer.MAX_VALUE; j++) { initNum ++; } } return initNum; } } } |
一般情况下,会打印如下内容:
已调用线程的interrupt方法
长时间任务运行结束,num=-2
线程的中断状态:true
可见,interrupt方法并不一定能中断线程。但是,如果改成下面的程序,情况会怎样呢?
import java.util.concurrent.TimeUnit; public class TestInterrupt { public static void main(String[] args) { Thread t = new MyThread(); t.start(); t.interrupt(); System.out.println("已调用线程的interrupt方法"); } static class MyThread extends Thread { public void run() { int num = -1; try { num = longTimeRunningInterruptMethod(2, 0); } catch (InterruptedException e) { System.out.println("线程被中断"); throw new RuntimeException(e); } System.out.println("长时间任务运行结束,num=" + num); System.out.println("线程的中断状态:" + Thread.interrupted()); } private static int longTimeRunningInterruptMethod(int count, int initNum) throws InterruptedException{ for(int i=0; i<count; i++) { TimeUnit.SECONDS.sleep(5); } return initNum; } } } |