Thread类的interrupt方法

一、线程中断

中断可以理解为一个线程的标志位,与线程中断有关的方法

  • interrupt方法

Thread类的实例方法:中断被调用线程,实际上只是改变了被调用线程 的内部中断状态,

==并不会中断线程==

必须注意API中的这一段描述

If this thread is blocked in an invocation of the wait(), wait(long), or wait(long, int) methods of the Object class, or of the join(), join(long), join(long, int), sleep(long), or sleep(long, int), methods of this class, then its interrupt status will be cleared and it will receive an InterruptedException.

如果该线程被阻塞在的调用wait() , wait(long) ,或者wait(long, int)的方法的Object类,或者在join() join(long) , join(long, int) , sleep(long) ,或sleep(long, int)这个类的方法,那么它的中断状态将被清除,它还将收到一个InterruptedException 。

  • interrupted方法

测试该线程对象是否被中断,会清除中断标志位

  • isInterrupted方法

测试该线程对象是否被中断,不会清除中断标志位

二、实例测试

1. 打断一个阻塞的线程,如sleep中的线程

@Slf4j(topic = "c.Test11")
public class Test11 {

    public static void main(String[] args) throws InterruptedException {
        Thread t1 = new Thread(() -> {
            log.debug("sleep...");
            try {
                Thread.sleep(5000); // wait, join
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        },"t1");

        t1.start();
        Thread.sleep(1000);
        log.debug("interrupt");
        t1.interrupt();
        Thread.sleep(1000);//防止interrupt方法未执行完毕,就继续执行下一行代码
        log.debug("打断标记:{}", t1.isInterrupted());
    }
}

==打断了正在休眠中的线程,抛出了中断异常,打断状态为false,被重置了==

2、打断一个正常运行的线程

Interrupt方法仅仅是对当前线程做了中断‘标记’,但是否真的结束线程运行,并不是由Java来完成的,需要开发者自己判断此标记,适当位置时机结束线程运行

测试:

@Slf4j(topic = "c.Test12")
public class Test12 {

    public static void main(String[] args) throws InterruptedException {
        Thread t1 = new Thread(() -> {
            while(true) {
                boolean interrupted = Thread.currentThread().isInterrupted();
                if(interrupted) {
                    log.debug("被打断了, 退出循环");
                    break;
                }
            }
        }, "t1");
        t1.start();

        Thread.sleep(1000);
        log.debug("interrupt");
        t1.interrupt();
    }
}

测试结果:

12:32:21.718 c.Test12 [main] - interrupt
12:32:21.720 c.Test12 [t1] - 被打断了, 退出循环

三、如何正确使用Interrupt方法来中止线程

@Slf4j(topic = "c.TPTInterrupt")
public class TPTInterrupt {
    private Thread thread;

    public void start() {
        thread = new Thread(() -> {
            while (true) {
                Thread current = Thread.currentThread();
                if (current.isInterrupted()) {
                    log.debug("料理后事");
                    break;
                }
                try {
                    log.debug("即将进入休眠");
                    Thread.sleep(1000);
                    log.debug("将结果保存");
                } catch (InterruptedException e) {
                    current.interrupt();
                }
// 执行监控操作
            }
        }, "监控线程");
        thread.start();
    }

    public void stop() {
        log.debug("打断线程");
        thread.interrupt();
    }

    public static void main(String[] args) throws InterruptedException {
        TPTInterrupt tptInterrupt = new TPTInterrupt();
        tptInterrupt.start();
        tptInterrupt.stop();
    }
}
12:48:23.214 c.TPTInterrupt [main] - 打断线程
12:48:23.214 c.TPTInterrupt [监控线程] - 即将进入休眠
12:48:23.217 c.TPTInterrupt [监控线程] - 料理后事

注意运行结果不是一定的

小结一下:线程启动后,我们执行了打断,

如果不是在

Thread.sleep(1000);

即休眠中被打断,那么中断标志位将被正常设置为true。那继续循环后将进入if中,料理后事然后退出

如果是在sleep中被打断,那么会抛出InterruptedException将会进入catch块中,再次进行打断(重新设置标志位)。

四、中断park线程

测试用例:

@Slf4j(topic = "c.Test14")
public class Test14 {

    private static void test4() {
        Thread t1 = new Thread(() -> {
            for (int i = 0; i < 5; i++) {
                log.debug("park...");
                LockSupport.park();
                //如果打断标记已经是 true, 则 park 会失效,所以这里使用interrupted方法清除了中断状态
                log.debug("打断状态:{}", Thread.interrupted());
            }
        });
        t1.start();

        sleep(1);
        t1.interrupt();
    }

    private static void test3() throws InterruptedException {
        Thread t1 = new Thread(() -> {
            log.debug("park...");
            LockSupport.park();
            log.debug("unpark...");
            // 执行了interrupt()后,中断状态设置为true
            log.debug("打断状态:{}", Thread.currentThread().isInterrupted());
        }, "t1");
        t1.start();

        sleep(1);
        t1.interrupt();

    }

    public static void main(String[] args) throws InterruptedException {
        test4();
    }
}

LockSupport.park();禁用线程,使其不被调度并处于休眠状态。

原文地址:https://www.cnblogs.com/heliusKing/p/12237854.html

时间: 2024-08-03 21:50:31

Thread类的interrupt方法的相关文章

C#中Thread类中Join方法的理解(转载)

指在一线程里面调用另一线程join方法时,表示将本线程阻塞直至另一线程终止时再执行      比如 Java代码   using System; namespace TestThreadJoin { class Program { static void Main() { System.Threading.Thread x = new System.Threading.Thread(new System.Threading.ThreadStart(f1)); x.Start(); Console

Thread类的sleep()方法和对象的wait()方法都可以让线程暂停执行,它们有什么区别? 线程的sleep()方法和yield()方法有什么区别?

Thread类的sleep()方法和对象的wait()方法都可以让线程暂停执行,它们有什么区别? sleep()方法(休眠)是线程类(Thread)的静态方法,调用此方法会让当前线程暂停执行指定的时间,将执行机会(CPU)让给其他线程,但是对象的锁依然保持,因此休眠时间结束后会自动恢复.wait()是Object类的方法,调用对象的wait()方法导致当前线程放弃对象的锁(线程暂停执行),进入对象的等待池(wait pool),只有调用对象的notify()方法(或notifyAll()方法)时

python语言中threading.Thread类的使用方法

1. 编程语言里面的任务和线程是很重要的一个功能.在python里面,线程的创建有两种方式,其一使用Thread类创建 # 导入Python标准库中的Thread模块 from threading import Thread # 创建一个线程 mthread = threading.Thread(target=function_name, args=(function_parameter1, function_parameterN)) # 启动刚刚创建的线程 mthread .start() f

线程中断:Thread类中interrupt()、interrupted()和 isInterrupted()方法详解

首先看看官方说明: interrupt()方法 其作用是中断此线程(此线程不一定是当前线程,而是指调用该方法的Thread实例所代表的线程),但实际上只是给线程设置一个中断标志,线程仍会继续运行. interrupted()方法 作用是测试当前线程是否被中断(检查中断标志),返回一个boolean并清除中断状态,第二次再调用时中断状态已经被清除,将返回一个false. isInterrupted()方法 作用是只测试此线程是否被中断 ,不清除中断状态  下面我们进行测试说明: 定义一个MyThr

2.匿名类,匿名类对象,private/protected/public关键字、abstract抽象类,抽象方法、final关键字的使用,多线程Thread类start方法原理

package com.bawei.multithread; //注意:模板方法我们通常使用抽象类或者抽象方法!这里我们为了方便在本类中使用就没有使用抽象类/抽象方法 public class TemplateThread { //如果这个方法不想被子类或者别人随意改动[这样子类就不能覆写该方法了],这里方法就要设置为final方法 public final void println(String message){ System.out.println("###################

java Thread 类 run 和 start 方法区别

public class ThreadModle { public static void main(String[] args) throws InterruptedException { Thread t = new Thread(new Runnable(){ @Override public void run() { System.out.println("Run threadID: " + Thread.currentThread().getId()); } }); Syst

线程Thread类的start()方法和run()方法

一.初识 java的线程是通过java.lang.Thread类来实现的.VM启动时会有一个由主方法所定义的线程.可以通过创建Thread的实例来创建新的线程.每个线程都是通过某个特定Thread对象所对应的方法run()来完成其操作的,方法run()称为线程体.通过调用Thread类的start()方法来启动一个线程. 在Java当中,线程通常都有五种状态,创建.就绪.运行.阻塞和死亡. 第一是创建状态.在生成线程对象,并没有调用该对象的start方法,这是线程处于创建状态. 第二是就绪状态.

Java并发编程:Thread类的使用

一.线程的状态 在正式学习Thread类中的具体方法之前,我们先来了解一下线程有哪些状态,这个将会有助于后面对Thread类中的方法的理解. 线程从创建到最终的消亡,要经历若干个状态.一般来说,线程包括以下这几个状态:创建(new).就绪(runnable).运行(running).阻塞(blocked).time waiting.waiting.消亡(dead). public enum State { /** * Thread state for a thread which has not

Thread类源码剖析

目录 1.引子 2.JVM线程状态 3.Thread常用方法 4.拓展点 一.引子 说来也有些汗颜,搞了几年java,忽然发现竟然没拜读过java.lang.Thread类源码,这次特地拿出来晒一晒.本文将剖析Thread类源码(本文后面源码全部默认JDK8),并讲解一些重要的拓展点.希望对大家能有一些帮助. 本文讲解主干全部出自源码和注释,保证了权威性.(注意:网上,某些书中很多观点都是错的,过时的,片面的,所以大家一定要看源码,重要事情说N遍,看源码!看源码!看源码......) 二.JVM