Java并发编程 interrupt()方法示例详解

 更新时间:2023年06月09日 16:13:19   作者:k3ruanren  
interrrupt()方法可以用来打断正在运行的线程,也可以打断sleep()、wait()、join()情况下的线程,但是这些情况下被打断线程的打断标记不同,这篇文章主要介绍了Java并发编程 interrupt()方法示例详解,需要的朋友可以参考下

interrupt()用法

打断正常运行的线程

interrrupt()方法可以用来打断正在运行的线程,也可以打断sleep()、wait()、join()情况下的线程,但是这些情况下被打断线程的打断标记不同。

import lombok.extern.slf4j.Slf4j;
import java.util.concurrent.TimeUnit;
@Slf4j
public class InterruptTest {
    public static void main(String[] args) throws InterruptedException {
        //创建一个线程
        Thread t1 = new Thread(() -> {
            //让线程一直死循环运行
            log.debug("t1开始运行.....");
            while(true){
            }
        },"t1");
        //启动线程t1
        t1.start();
        //main主线程一秒后进行打断操作
        TimeUnit.MILLISECONDS.sleep(1000);
        log.debug("interrupt.....");
        t1.interrupt();
    }
}

通过控制台,可以很清晰的看到,main主线程在执行完打断操作后,t1线程并未终止运行,而是继续执行:

但是如果我们查看线程t1的打断标记会发现,t1线程的打断标记确实为true:

Boolean interrupted = Thread.currentThread().isInterrupted();

这是因为main主线程执行interrupt打断操作,只是通知t1线程,我现在要打断你,但是具体的执行操作还得看t1线程,即t1线程收到main主线程的打断通知后,由t1线程自己觉得是继续运行还是被打断,从而让出cpu,这样的好处在于线程t1如果在执行某些很重要的任务,突然被其他线程强制打断可能会造成很严重的后果,这时可以让t1线程自己选择是否停止工作,也可以在停止工作之前做一些料理后事的工作 。

import lombok.extern.slf4j.Slf4j;
import java.util.concurrent.TimeUnit;
@Slf4j
public class InterruptTest {
    public static void main(String[] args) throws InterruptedException {
        //创建一个线程
        Thread t1 = new Thread(() -> {
            //让线程一直死循环运行
            log.debug("t1开始运行.....");
            while(true){
                Boolean interrupted = Thread.currentThread().isInterrupted();
                //选择被打断后的执行操作
                if(interrupted){
                    log.debug("被打断,停止运行...");
                    break;
                }
            }
        },"t1");
        //启动线程t1
        t1.start();
        //main主线程一秒后进行打断操作
        TimeUnit.MILLISECONDS.sleep(1000);
        log.debug("interrupt.....");
        t1.interrupt();
    }
}

14:41:02.906 [t1] DEBUG InterruptTest - t1开始运行.....
14:41:03.908 [main] DEBUG InterruptTest - interrupt.....
14:41:03.908 [t1] DEBUG InterruptTest - 被打断,停止运行...

打断sleep状态的线程

import lombok.extern.slf4j.Slf4j;
import java.util.concurrent.TimeUnit;
@Slf4j
public class InterruptTest {
    public static void main(String[] args) throws InterruptedException {
        //创建一个线程
        Thread t1 = new Thread(() -> {
            //让线程一直死循环运行
            log.debug("t1开始运行.....");
            //t1线程休眠3秒
            try {
                log.debug("t1 is sleeping...");
                TimeUnit.SECONDS.sleep(3);
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
        },"t1");
        //启动线程t1
        t1.start();
        //main主线程一秒后进行打断操作
        TimeUnit.MILLISECONDS.sleep(1000);
        log.debug("interrupt.....");
        t1.interrupt();
        //查看t1线程的打断标记
        Boolean interrupted = t1.isInterrupted();
        log.debug(interrupted.toString());
    }

打断sleep状态的线程,会抛出InterruptedException异常,并且打断标记是false而不是true:

14:50:25.532 [t1] DEBUG InterruptTest - t1开始运行.....
14:50:25.536 [t1] DEBUG InterruptTest - t1 is sleeping...
14:50:26.533 [main] DEBUG InterruptTest - interrupt.....
14:50:26.544 [main] DEBUG InterruptTest - false
Exception in thread "t1" java.lang.RuntimeException: java.lang.InterruptedException: sleep interrupted
	at InterruptTest.lambda$main$0(InterruptTest.java:17)
	at java.base/java.lang.Thread.run(Thread.java:829)
Caused by: java.lang.InterruptedException: sleep interrupted
	at java.base/java.lang.Thread.sleep(Native Method)
	at java.base/java.lang.Thread.sleep(Thread.java:334)
	at java.base/java.util.concurrent.TimeUnit.sleep(TimeUnit.java:446)
	at InterruptTest.lambda$main$0(InterruptTest.java:15)
	... 1 more
Process finished with exit code 0

两阶段终止模式 Two Phase Termination

在线程t1中如何优雅的终止线程t2?

  • 使用stop()方法终止线程,这显然是不好的行为,因为一个线程调用了stop()方法,那么这个线程就被彻底杀死了,如果该线程正在访问一些共享资源并且加了锁,那么stop()之后该线程将再也不能释放锁,其他线程也就无法访问那些共享资源了。
  • 使用System.exit()方法,这也是错误的选择,这会终止整个程序!

正确的做法是采用两阶段终止模式,具体流程如下图所示:

import lombok.extern.slf4j.Slf4j;
import java.util.concurrent.TimeUnit;
@Slf4j
public class TwoPhaseTest {
    public static void main(String[] args) throws InterruptedException {
        TwoPhaseTermination tpt = new TwoPhaseTermination();
        tpt.start();
        TimeUnit.SECONDS.sleep(4);
        tpt.stop();
    }
}
/**
 * 监控类
 */
@Slf4j
class TwoPhaseTermination{
    //监控线程
    private Thread monitor;
    //线程启动方法
    public void start(){
        monitor = new Thread(()->{
            while(true){
                Thread thread = Thread.currentThread();
                Boolean interrupted = thread.isInterrupted();
                if(interrupted){
                    log.debug("料理后事.....");
                    break;
                }
                try {
                    TimeUnit.SECONDS.sleep(1);
                    //每隔一秒钟执行监控任务
                    log.debug("监控中....");
                } catch (InterruptedException e) {
                    e.printStackTrace();
                    //如果在sleep状态被打断,那么中断标记为false,需要手动置为true
                    thread.interrupt();
                }
        }});
        //启动线程
        monitor.start();
    }
    //线程终止方法
    public void stop(){
        //打断线程
        monitor.interrupt();
    }
}

15:38:11.046 [Thread-0] DEBUG TwoPhaseTermination - 监控中....
15:38:12.054 [Thread-0] DEBUG TwoPhaseTermination - 监控中....
15:38:13.060 [Thread-0] DEBUG TwoPhaseTermination - 监控中....
java.lang.InterruptedException: sleep interrupted
    at java.base/java.lang.Thread.sleep(Native Method)
    at java.base/java.lang.Thread.sleep(Thread.java:334)
    at java.base/java.util.concurrent.TimeUnit.sleep(TimeUnit.java:446)
    at TwoPhaseTermination.lambda$start$0(TwoPhaseTest.java:33)
    at java.base/java.lang.Thread.run(Thread.java:829)
15:38:14.014 [Thread-0] DEBUG TwoPhaseTermination - 料理后事.....

Process finished with exit code 0

打断park()线程

import lombok.extern.slf4j.Slf4j;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.LockSupport;
@Slf4j
public class ParkTest {
    public static void main(String[] args) throws InterruptedException {
        test();
    }
    private static void test() throws InterruptedException {
        Thread t1 = new Thread(()->{
           log.debug("park......");
           LockSupport.park();//线程在此卡住,不继续向下执行
           log.debug("unpark.......");
           log.debug("打断状态:{}",Thread.currentThread().isInterrupted());
        },"t1");
        t1.start();
        //主线程main休眠2秒
        TimeUnit.SECONDS.sleep(2);
        //打断t1线程
        t1.interrupt();
    }
}

15:51:24.581 [t1] DEBUG ParkTest - park......
15:51:26.582 [t1] DEBUG ParkTest - unpark.......
15:51:26.584 [t1] DEBUG ParkTest - 打断状态:true

到此这篇关于Java并发编程 interrupt()方法的文章就介绍到这了,更多相关Java并发编程 interrupt()方法内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • Java中的源文件、字节码文件解读

    Java中的源文件、字节码文件解读

    这篇文章主要介绍了Java中的源文件、字节码文件,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2024-03-03
  • 解决java.lang.NoClassDefFoundError:lombok/Data报错问题

    解决java.lang.NoClassDefFoundError:lombok/Data报错问题

    在Java开发中,使用Lombok库简化代码非常普遍,今天在启动拉取的git代码时,遇到了java.lang.NoClassDefFoundError:lombok/Data的报错,经过检查,发现错误的原因是将Date误写为Data,且错误地引用了lombok.Data包
    2024-09-09
  • MyBatis中如何优雅的使用枚举详解

    MyBatis中如何优雅的使用枚举详解

    枚举类型是我们在开发中经常遇到的一个类型,最近在学习MyBatis,但是发现网上没有详细介绍MyBatis如何使用枚举的相关文章,索性就自己写一篇,下面这篇文章主要给大家介绍了关于在MyBatis中如何优雅的使用枚举的相关资料,需要的朋友可以参考借鉴。
    2017-08-08
  • maven中profile动态打包不同环境配置文件的实现

    maven中profile动态打包不同环境配置文件的实现

    开发项目时会遇到这个问题:开发环境,测试环境,生产环境的配置文件不同, 打包时经常要手动更改配置文件,本文就来介绍一下maven中profile动态打包不同环境配置文件的实现,感兴趣的可以了解一下
    2023-10-10
  • 带你快速搞定java多线程(4)

    带你快速搞定java多线程(4)

    这篇文章主要介绍了java多线程编程实例,分享了几则多线程的实例代码,具有一定参考价值,加深多线程编程的理解还是很有帮助的,需要的朋友可以参考下
    2021-07-07
  • Java Fluent Mybatis 项目工程化与常规操作详解流程篇 下

    Java Fluent Mybatis 项目工程化与常规操作详解流程篇 下

    Java中常用的ORM框架主要是mybatis, hibernate, JPA等框架。国内又以Mybatis用的多,基于mybatis上的增强框架,又有mybatis plus和TK mybatis等。今天我们介绍一个新的mybatis增强框架 fluent mybatis关于项目工程化与常规操作流程
    2021-10-10
  • 用Maven打成可执行jar,包含maven依赖,本地依赖的操作

    用Maven打成可执行jar,包含maven依赖,本地依赖的操作

    这篇文章主要介绍了用Maven打成可执行jar,包含maven依赖,本地依赖的操作,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2020-08-08
  • Java收集的雪花算法代码详解

    Java收集的雪花算法代码详解

    这篇文章主要介绍了Java实现雪花算法的详细代码,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2021-10-10
  • 在win10系统下,如何配置Spring Cloud alibaba Seata以及出现问题时怎么解决

    在win10系统下,如何配置Spring Cloud alibaba Seata以及出现问题时怎么解决

    今天教大家如何在win10系统下,配置Spring Cloud alibaba Seata以及出现问题时怎么解决,文中有非常详细的介绍及代码示例,需要的朋友可以参考下
    2021-06-06
  • java如何自定义注解

    java如何自定义注解

    这篇文章主要介绍了java如何自定义注解问题,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2024-02-02

最新评论