一文了解JAVA线程的中断(Interrupt)机制

简介: 一文了解JAVA线程的中断(Interrupt)机制

介绍


Java的中断是一种协作机制,也就是说通过中断并不能直接中断另外一个线程,而需要被中断的线程自己处理中断。

在Java的中断模型中,每个线程都有一个boolean标识,代表着是否有中断请求(该请求可以来自所有线程,包括被中断的线程本身)。例如,当线程t1想中断线程t2,只需要在线程t1中将线程t2对象的中断标识置为true,然后线程2可以选择在合适的时候处理该中断请求,甚至可以不理会该请求,就像这个线程没有被中断一样。


中断方法


线程中断相关的方法主要是下面的3方法,他们具体的作用见下面的表格:

方法名 介绍
void interrupt() 中断线程,设置线程的中断位true
boolean isInterrupted() 检查线程的中断标记位,true-中断状态, false-非中断状态
static boolean interrupted() 静态方法,返回当前线程的中断标记位,同时清除中断标记,改为false。比如当前线程已中断,调用interrupted(),返回true, 同时将当前线程的中断标记位改为false, 再次调用interrupted(),会发现返回false

记忆方法推荐:

  • interrupt()是一个动词,表示中断线程。
  • Interrupted是一个形容词,用于检查线程的中断位,而isInterrupted()方法只是简单的检查,interrupted()处理的更加复杂。


可中断的阻塞


针对线程处于由sleep, wait, joinLockSupport.park等方法调用产生的阻塞状态时,调用interrupt方法,会抛出异常InterruptedException,同时会清除中断标记位,自动改为false。


不可中断的阻塞


  1. java.io包中的同步Socket I/O
  2. java.io包中的同步I/O
  3. Selector的异步I/O
  4. sychronized加的锁


实践案例


中断sleep、wait、join等方法


private static void test1() throws InterruptedException {
        Thread t1 = new Thread(() -> {
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                log.error("error", e);
            }
        }, "t1");
        t1.start();
        Thread.sleep(500);
        t1.interrupt();
        Thread.sleep(100);
        log.info(" interrupt status : {}", t1.isInterrupted());
}

1671089657989.jpg

结论: 阻塞方法sleep响应中断,抛出InterruptedException,同时清除中断标记位为false。


中断LockSupport.park方法


public static void test3() throws InterruptedException {
        Thread t3 = new Thread(() -> {
            log.debug("t3 park.....");
            LockSupport.park();
            log.debug("t3 unpark.....");
            log.debug("interrupt status: [{}]", Thread.currentThread().isInterrupted());
            log.debug("t3 第二次 park.....");
            LockSupport.park();
            log.debug("t3 中断位为true, park失效.....");
        }, "t3");
        t3.start();
        Thread.sleep(1000);
        t3.interrupt();
    }

1671089680990.jpg

结论: 阻塞方法park响应中断, 不会抛出异常,同时不会清除中断标记位,任为true。


中断正常方法


private static void test2() throws InterruptedException {
        Thread t2 = new Thread(() -> {
            while (true) {
                boolean isInterrupted = Thread.currentThread().isInterrupted();
                if (isInterrupted) {
                    log.info("interrupt status: {}", isInterrupted);
                    break;
                }
            }
        }, "t2");
        t2.start();
        Thread.sleep(500);
        t2.interrupt();
        Thread.sleep(100);
        log.info(" thread status, {}, interrupt status : {}", t2.getState(), t2.isInterrupted());
    }

1671089694506.jpg

结论: 打断正常运行的线程, 不会清空打断状态,同时线程结束后,重置中断状态位。


常见模式


这里提供针对interrupt中断使用的一种常见模式,方便大家在后续的开发过程中使用。


两阶段中止模式


使用场景


在一个线程中“优雅”地停止另一个线程的工作,在停止的时候给另一个线程"料理后事"的机会。比如有个监控线程在做监控,在主线程可以终止他的工作。


代码展示

class MonitorTask {
    private Thread thread;
    // 开始监控
    public void start() {
        thread = new Thread(() -> {
           while (true) {
               Thread curr = thread.currentThread();
               // 如果当前线程是中断状态
               if(curr.isInterrupted()) {
                   log.debug("清理资源,料理后事");
                   break;
               }
               try {
                   // 监控执行工作...
                   log.debug("监控执行ing");
                   Thread.sleep(1000);
               } catch (InterruptedException e) {
                   log.error("error", e);
                   // 此处中断位被清除,变为false, 重新改为true,进入循环,处理线程后事
                   curr.interrupt();
               }
           }
        }, "监控线程");
        thread.start();
    }
    // 终止线程
    public void stop() {
        thread.interrupt();
    }
}
MonitorTask monitorTask = new MonitorTask();
monitorTask.start();
Thread.sleep(1500);
monitorTask.stop();

1671089722696.jpg

目录
相关文章
|
8天前
|
监控 算法 Java
Java中的内存管理:理解Garbage Collection机制
本文将深入探讨Java编程语言中的内存管理,特别是垃圾回收(Garbage Collection, GC)机制。我们将从基础概念开始,逐步解析垃圾回收的工作原理、不同类型的垃圾回收器以及它们在实际项目中的应用。通过实际案例,读者将能更好地理解Java应用的性能调优技巧及最佳实践。
32 0
|
2天前
|
存储 缓存 Java
java线程内存模型底层实现原理
java线程内存模型底层实现原理
java线程内存模型底层实现原理
|
6天前
|
Java 程序员
深入理解Java异常处理机制
【9月更文挑战第20天】在Java编程世界中,异常处理是一项基础而重要的技能。本文将通过通俗易懂的语言和生动的比喻,带你走进Java异常的世界,了解它们的本质、分类以及如何优雅地处理这些不请自来的特殊“客人”。从简单的try-catch语句到复杂的异常链追踪,我们将一步步揭开异常处理的面纱,让你在遇到问题时不再手足无措。
39 21
|
7天前
|
缓存 Java 应用服务中间件
Java虚拟线程探究与性能解析
本文主要介绍了阿里云在Java-虚拟-线程任务中的新进展和技术细节。
|
4天前
|
Java 开发者
Java中的多线程基础与应用
【9月更文挑战第22天】在Java的世界中,多线程是一块基石,它支撑着现代并发编程的大厦。本文将深入浅出地介绍Java中多线程的基本概念、创建方法以及常见的应用场景,帮助读者理解并掌握这一核心技术。
|
6天前
|
Java 程序员 数据库连接
深入理解Java中的异常处理机制
【9月更文挑战第20天】在Java编程的世界中,异常处理是一块不可忽视的拼图。本文将带你深入探讨Java的异常处理机制,从异常的基础概念到高级应用,通过实际代码示例,揭示如何优雅地管理程序中的错误和异常情况。我们将一起学习如何使用try-catch语句捕获异常,了解finally块的重要性,以及何时使用throws关键字。此外,我们还会探索自定义异常类的创建和利用,以及最佳实践来优化你的异常处理策略。无论你是Java新手还是有经验的开发者,这篇文章都将为你提供有价值的见解和技巧,帮助你编写更加健壮和易于维护的代码。
21 7
|
6天前
|
Java
领略Lock接口的风采,通过实战演练,让你迅速掌握这门高深武艺,成为Java多线程领域的武林盟主
领略Lock接口的风采,通过实战演练,让你迅速掌握这门高深武艺,成为Java多线程领域的武林盟主
21 7
|
2天前
|
Java 数据库连接 开发者
深入理解Java中的异常处理机制
本文旨在全面解析Java的异常处理机制,从基础概念到高级应用,逐步揭示其在软件开发中的重要性。通过实例分析,帮助读者更好地理解和运用异常处理,提升代码的健壮性和可维护性。
|
5天前
|
Java 程序员
Java中的多线程基础与实践
【9月更文挑战第21天】本文旨在引导读者深入理解Java多线程的核心概念,通过生动的比喻和实例,揭示线程创建、同步机制以及常见并发工具类的使用。文章将带领读者从理论到实践,逐步掌握如何在Java中高效地运用多线程技术。
|
3天前
|
Java 调度 开发者
Java中的多线程编程:从基础到实践
本文旨在深入探讨Java多线程编程的核心概念和实际应用,通过浅显易懂的语言解释多线程的基本原理,并结合实例展示如何在Java中创建、控制和管理线程。我们将从简单的线程创建开始,逐步深入到线程同步、通信以及死锁问题的解决方案,最终通过具体的代码示例来加深理解。无论您是Java初学者还是希望提升多线程编程技能的开发者,本文都将为您提供有价值的见解和实用的技巧。
10 2