美文网首页Java 杂货铺Android开发经验谈Android开发
Java中如何正确地中断一个线程?

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

作者: 增其Mrlu | 来源:发表于2017-10-14 15:11 被阅读164次

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

1.线程的状态

  • NEW (新建)
    一个尚未启动的线程处于这一状态。(A thread that has not yet started is in this state.)
  • RUNNABLE (可运行)
    一个正在 Java 虚拟机中执行的线程处于这一状态。(A thread executing in the Java virtual machine is in this state.)
  • BLOCKED (阻塞)
    一个正在阻塞等待一个监视器锁的线程处于这一状态。(A thread that is blocked waiting for a monitor lock is in this state.)
  • WAITING (等待)
    一个正在无限期等待另一个线程执行一个特别的动作的线程处于这一状态。(A thread that is waiting indefinitely for another thread to perform a particular action is in this state.)
  • TIMED_WAITING (计时等待)
    一个正在限时等待另一个线程执行一个动作的线程处于这一状态。(A thread that is waiting for another thread to perform an action for up to a specified waiting time is in this state.)
  • TERMINATED (终止)
    一个已经退出的线程处于这一状态。(A thread that has exited is in this state.)

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

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()的时候分为两种情况:

  • 线程正常运行的情况(没有阻塞),那么该线程的中断标志位被设置为true,如果没有在线程中读取中断状态,退出线程里的循环的话,线程将继续执行。
  • 线程被阻塞的情况,由于线程已经被阻塞,要中断线程的话,就需要将线程的中断状态清除,同时抛出InterruptedException异常,线程才得以中断。
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/

相关文章

  • 一个简单的带中断策略的Thread用例

    使用: 如何优雅的"停止"一个正在运行的JAVA线程如何正确地停止一个线程?关闭线程的正确方法:“优雅”的中断Ja...

  • Java多线程:如何停止/中断一个运行中的线程?

    # 面试题: 如何正确地停止/中断一个线程 哪些情况下线程会停止 如何处理不可中断的阻塞 # 核心思想 使用int...

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

    本文主要整理了关于线程中断的相关知识点。 1.线程的状态 NEW (新建)一个尚未启动的线程处于这一状态。(A t...

  • (4)线程中断

    什么是线程中断 java中的线程中断并不是指强制线程中断执行,而是指调用线程中断起到一个通知作用,让线程知道自己被...

  • JAVA并发编程(三)线程协作与共享

    1. 线程中断 java线程中断是协作式,而非抢占式 1.1. 线程中断相关方法 interrupt()将线程的中...

  • Java线程中断

    本文主要介绍Java线程中断一些相关的概念以及注意点 Java线程的中断并不是强制的中断,调用线程中断的方法时只是...

  • java中线程中断interrupt

    java中涉及线程中断主要有3个方法 1.interrupt(),在一个线程中调用另一个线程的interrupt(...

  • 一种强制关闭线程的方法

    在Java中,停止一个线程的主要机制是中断,中断并不是强迫终止一个线程,它是一种协作机制,是给线程传递一个取消信号...

  • java 中断

    JAVA多线程之中断机制(如何处理中断?)https://blog.csdn.net/pange1991/arti...

  • 线程中断

    什么是线程中断?线程中断即线程运行过程中被其他线程打断了。 线程中断的重要方法2.1 java.lang.Thre...

网友评论

本文标题:Java中如何正确地中断一个线程?

本文链接:https://www.haomeiwen.com/subject/aazzyxtx.html