Java 杂货铺Android开发经验谈Android开发

Java中如何正确地中断一个线程?

2017-10-14  本文已影响164人  增其Mrlu

本文主要整理了关于线程中断的相关知识点。

1.线程的状态

线程的状态转换图 来自@牛客网:

2.如何正确中断一个线程?

2.1 利用标志位。

这种简单地设置标志位来中断线程的方法,其弊端是当线程被阻塞时,没办法读到标志位,也中断不了线程。

public class TestThread extends Thread {   
    private volatile boolean finished = false;    
    public void stopThread() {        
        finished = true;
    }
    @Override    
    public void run() {        
        while (!finished) {          
            // do something
        }   
    }
}

2.2 调用Thread.interrupt()

interrupt()的本质也是利用了标志位来中断线程,它并不会真正地中断一个线程,而是通过改变标志位,让线程自己根据标志位和时机,灵活地决定要不要退出线程

关于中断线程,JDK提供了三个与之相关的方法,之前被废弃的方法这里就不多赘述。

2.2.1 public void interrupt()
public void interrupt()
中断线程。 
如果线程在调用 Object 类的 wait()、wait(long) 或 wait(long, int) 方法,
或者该类的 join()、join(long)、join(long, int)、sleep(long) 或 sleep(long, int) 方法过程中受阻,
则其中断状态将被清除,它还将收到一个 InterruptedException。

所以调用interrupt()的时候分为两种情况:

2.2.2 public static boolean interrupted()
public static boolean interrupted()
测试当前线程是否已经中断。线程的中断状态由该方法清除。换句话说,如果连续两次调用该方法,则第二次调用将返回 false(在第一次调用已清除了其中断状态之后,且第二次调用检验完中断状态前,当前线程再次中断的情况除外)。 

interrupted(),首先会返回当前线程的中断状态,然后会将线程的中断状态清除,也就是将标志位设置为false。

2.2.3 public boolean isInterrupted()
public boolean isInterrupted()
测试线程是否已经中断。线程的中断状态不受该方法的影响。 

而isInterrupted(),只会返回线程中断状态,不会修改标志位。

这两者的差别 简单地说就是:

Thread.isInterrupted() 用来读取中断状态, Thread.interrupted() 用来读取中断状态和清除标志位。

tips:在线程执行完毕之后,线程的中断状态会被修改为false。

2.2.4 例子:
public class TestThread extends Thread {
     @Override
     public void run() {
          while (!isInterrupted()) {
                try {
                   // do something
                   
                    } catch (InterruptedException e) {
                    Thread.currentThread().interrupt();
                }
          }
     }
}

TestThread testThread = new TestThread();
testThread.start();
// 一段时间以后
testThread.interrupt();

总的来说,当新开的线程被阻塞了,在调用interrupt()的时候,线程的中断状态清除,同时抛出InterruptedException异常,注意,这个时候中断状态被清除了!你需要在catch语句里面重新调用interrupt(),来维持中断状态,否则,由于中断状态被清除,当程序继续执行到while (!isInterrupted())的时候,线程是不会停下来的。

参考资料:

https://www.ibm.com/developerworks/cn/java/j-jtp05236.html

http://ibruce.info/2013/12/19/how-to-stop-a-java-thread/

上一篇 下一篇

猜你喜欢

热点阅读