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

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,如果没有在线程中读取中断状态,退出线程里的循环的话,线程将继续执行。
线程被阻塞的情况,<u>由于线程已经被阻塞,要中断线程的话,就需要将线程的中断状态清除,同时抛出InterruptedException异常,线程才得以中断。</u>

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())的时候,线程是不会停下来的。

欢迎加入学习交流群569772982,大家一起学习交流。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 214,837评论 6 496
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,551评论 3 389
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 160,417评论 0 350
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,448评论 1 288
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,524评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,554评论 1 293
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,569评论 3 414
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,316评论 0 270
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,766评论 1 307
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,077评论 2 330
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,240评论 1 343
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,912评论 5 338
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,560评论 3 322
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,176评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,425评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,114评论 2 366
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,114评论 2 352

推荐阅读更多精彩内容