如何中断Java线程?查看API,不就是用interrupt()方法么?而线程是否已经中断则用Thread.currentThread().isInterrupted()返回true/false:
public class ThreadDemo extends Thread{
public static void main(String[] args) throws InterruptedException {
Thread thread = new ThreadDemo();
thread.start();
thread.sleep(100);
thread.interrupt(); //中断线程
}
@Override
public void run() {
while(!Thread.currentThread().isInterrupted()) {
System.out.println("thread running");
try {
Thread.sleep(100);
}catch(InterruptedException e)
{
System.out.println("InterruptedException");
}
}
System.out.println("thread interrupted");
}
}
运行结果:
thread running
InterruptedException
thread running
thread running
thread running
thread running
...
很快发现这方法似乎有问题,线程没有成功中断,于是在处理InterruptedException异常后调用break跳出while循环:
public class ThreadDemo extends Thread{
public static void main(String[] args) throws InterruptedException {
Thread thread = new ThreadDemo();
thread.start();
thread.sleep(100);
thread.interrupt(); //中断线程
}
@Override
public void run() {
while(!Thread.currentThread().isInterrupted()) {
System.out.println("thread running");
try {
Thread.sleep(100);
}catch(InterruptedException e)
{
System.out.println("InterruptedException");
break;
}
}
System.out.println("thread interrupted");
}
}
运行结果(线程成功中断):
thread running
InterruptedException
thread interrupted
接着在网上搜索了一下,写了一些例子研究后明白如何写一个可中断的线程。
首先发现在调用线程的start()后,立即调用interrupt()中断线程,线程停止了――被挡在while条件的外面:
public class ThreadDemo extends Thread{
public static void main(String[] args) throws InterruptedException {
Thread thread = new ThreadDemo();
thread.start();
//thread.sleep(100);
thread.interrupt(); //中断线程
}
@Override
public void run() {
System.out.println("in run()");
while(!Thread.currentThread().isInterrupted()) {
System.out.println("thread running");
try {
Thread.sleep(100);
}catch(InterruptedException e)
{
System.out.println("InterruptedException");
//break;
}
}
System.out.println("thread interrupted");
}
}
运行结果:
in run()
thread interrupted
然后按照网上说的在异常处理时再次中断,原来这样就能成功地用interrupt方法中断线程:
public class ThreadDemo extends Thread{
public static void main(String[] args) throws InterruptedException {
Thread thread = new ThreadDemo();
thread.start();
thread.sleep(100);
thread.interrupt(); //中断线程
}
@Override
public void run() {
while(!Thread.currentThread().isInterrupted()) {
System.out.println("thread running");
try {
Thread.sleep(100);
}catch(InterruptedException e)
{
System.out.println("InterruptedException");
Thread.currentThread().interrupt(); //再次中断线程
//break;
}
}
System.out.println("thread interrupted");
}
}
运行结果(线程成功中断):
thread running
InterruptedException
thread interrupted
为什么在调用interrupt()前加上sleep(),导致的结果不同呢?
我认为Thread对象只有在调用start()时才分配资源创建线程提供给CPU调度。而这过程需要时间,因为时间差,导致了在进入run()方法前,中断标志已经被set on,于是被挡在while条件上。
而再次中断线程,中断标志被set on了,然后循环回到while条件判断,于是退出循环。
而线程被中断后,该对象依然存在的,只是线程不能再次调用start()否则会报异常IllegalThreadStateException。
public class ThreadDemo extends Thread{
public static void main(String[] args){
try{
ThreadDemo thread = new ThreadDemo();
thread.start();
thread.sleep(100);
thread.interrupt(); //中断线程
thread.sleep(100);
thread.printStr();
thread.interrupt(); //第三次中断线程
thread.printStr();
thread.join();
}catch(InterruptedException e){
e.printStackTrace();
}
}
private void printStr(){
System.out.println("thread obj");
}
@Override
public void run() {
while(!Thread.currentThread().isInterrupted()) {
System.out.println("thread running");
try {
Thread.sleep(100);
}catch(InterruptedException e)
{
System.out.println("InterruptedException");
Thread.currentThread().interrupt(); //再次中断线程
}
}
System.out.println("thread interrupted");
}
}
运行结果:
thread running
InterruptedException
thread interrupted
thread obj
thread obj
简单总结:
1. 线程start()后马上调用interrupt(),在进入run()时中断标志已经被set on;
2. 在处理sleep()可能抛出的InterruptedException时,再次中断线程即可成功中断;
3. 注意interrupt()方法是set on 中断标志的,interrupted()方法是判断后并清除中断标志的。
isInterrupted()和interrputed()方法的区别
public static boolean interrupted()
测试当前线程是否已经中断。线程的中断状态由该方法清除。换句话说,如果连续两次调用该方法,则第二次调用将返回 false(在第一次调用已清除了其中断状态之后,且第二次调用检验完中断状态前,当前线程再次中断的情况除外)。
public boolean isInterrupted()
测试线程是否已经中断。线程的中断状态不受该方法的影响。
两者都是如果该线程已经中断,则返回 true;否则返回 false。
参考文章 《Java 可中断线程》 http://blog.csdn.net/sapphiron/archive/2008/10/05/3018053.aspx 此文介绍更多的处理其他阻塞情况的中断方法。