Java中interrupt()方法详解附带demo
Thread.interrupt()的作用是通知线程应该中断了,到底中断还是继续运行,应该由被通知的线程自己处理。当对一个线程,调用 interrupt() 时,
1.如果线程处于被阻塞状态(例如处于sleep, wait, join 等状态),那么线程将立即退出被阻塞状态,并抛出一个InterruptedException异常。仅此而已。
2.如果线程处于正常活动状态,那么会将该线程的中断标志设置为 true,仅此而已。被设置中断标志的线程将继续正常运行,不受影响。
首先说第二条,线程正常执行,通过interrupt()方法将其中断标志设置为true,在线程中使用Thread.interrupted()方法判断当前线程是否被设置中断标志。
public class StopThread implements Runnable {
public static void main(String[] args) {
StopThread stopThread = new StopThread();
Thread thread = new Thread(stopThread);
thread.start();
System.out.println("thread starting...");
try {
Thread.sleep(3000);
thread.interrupt();
System.out.println("interrupt thread!");
Thread.sleep(3000);
thread.join();
System.out.println("main stop!");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
@Override
public void run() {
int i = 1;
while (!Thread.interrupted())
i++;
System.out.println("i=" + i);
System.out.println("thread stop!");
}
}
输出:
thread starting...
interrupt thread!
i=-937646695
thread stop!
main stop!
这里再说一下interrupted(),贴一下jdk1.8源码的方法注释,当调用这个方法会将中断标志重置,如果线程继续执行,下一次调用这个方法返回为false,除非再次调用interrupt()方法设置一次。简单来说就是一次interrupt()只对应一次interrupted()的true状态。
Tests whether the current thread has been interrupted. The
<i>interrupted status</i> of the thread is cleared by this method. In
other words, if this method were to be called twice in succession, the
second call would return false
接下来研究下第一条,再写一个简单的demo,可以看到线程正在sleep中,调用了interrupt()方法后,直接进入catch (InterruptedException e) {}中,然后继续执行线程后续操作。所以在catch中写停止线程的语句,即可达到目的。
public class StopThread implements Runnable {
public static void main(String[] args) {
StopThread stopThread = new StopThread();
Thread thread = new Thread(stopThread);
thread.start();
System.out.println("thread starting...");
try {
Thread.sleep(1000);
thread.interrupt();
System.out.println("interrupt thread!");
Thread.sleep(3000);
thread.join();
System.out.println("main stop!");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
@Override
public void run() {
try {
Thread.sleep(10000);
} catch (InterruptedException e) {
System.out.println("throw InterruptedException!");
e.printStackTrace();
}
System.out.println("thread stop!");
}
}
输出
thread starting...
interrupt thread!
throw InterruptedException!
thread stop!
java.lang.InterruptedException: sleep interrupted
at java.lang.Thread.sleep(Native Method)
at program.javaTest.threadtest.StopThread.run(StopThread.java:30)
at java.lang.Thread.run(Thread.java:745)
main stop!
那么还有个情况,就是调用interrupt()时线程没有处于阻塞,然后线程开始了sleep等三种方法阻塞,这时线程同样会跳入catch (InterruptedException e) {}中,因为中断标志此时为true。
public class StopThread implements Runnable {
public static void main(String[] args) {
StopThread stopThread = new StopThread();
Thread thread = new Thread(stopThread);
thread.start();
System.out.println("thread starting...");
try {
thread.interrupt();
System.out.println("isInterrupted : " + thread.isInterrupted());
Thread.sleep(3000);
thread.join();
System.out.println("main stop!");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
@Override
public void run() {
long l = System.currentTimeMillis();
while (System.currentTimeMillis() - l < 5000);
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
System.out.println("entry catch block!");
e.printStackTrace();
}
System.out.println("thread stop!");
}
}
输出
thread starting...
isInterrupted : true
entry catch block!
java.lang.InterruptedException: sleep interrupted
at java.lang.Thread.sleep(Native Method)
at program.javaTest.threadtest.StopThread.run(StopThread.java:30)
at java.lang.Thread.run(Thread.java:745)
thread stop!
main stop!
这个demo中多了一个thread.isInterrupted()方法,它也是用来测试线程中断表示,不同的是,它是实例方法,所以返回的是实例thread的中断标志,这样用来在线程外部管理线程的地方得到线程中断状态;另外isInterrupted()方法不会重置中断标志。用这个方法时有另外一个发现,当线程进入catch后,中断标志重置为false!!!
P.S.interrupt()方法就讲这么多,它和信号变量一起使用可以达到很好的中断线程目的。但是又有了新的问题,现在能够处理sleep等3个阻塞方法,如果线程阻塞在其他方法上,比如IO中的read,该如何处理。这个之后会放在另外一篇博文中详细介绍。