java中使用interrupt通知线程停止详析

Java中使用interrupt通知线程停止详析

概述

在Java多线程编程中,有时候需要在某个条件满足时中断线程的执行。Java中提供了一种机制,即通过中断(interrupt)的方式通知线程停止。本文将详细阐述Java中使用interrupt通知线程停止的完整攻略。

了解中断机制

在Java中,线程有一个boolean类型的中断标记,初始值为false。当线程调用了interrupt()方法时,中断标记就会被设置为true,表示该线程收到了中断信号。线程在被中断时,可以通过isInterrupted()方法检查中断标记是否被设置了。

如何停止线程

有两种方式停止线程,分别是:

  1. 使用中断(interrupt)机制

    在线程中处理中断信号,以此来停止线程。比如,在线程中不断地检查中断标记,一旦中断标记为true,就立即结束线程。

  2. 使用共享变量

    在线程外部设置一个共享变量,在满足某个条件时,将变量值设置为true。线程在执行时不断检查共享变量的值,如果发现变量值为true,就立即结束线程。

如何使用中断机制停止线程

1. 在线程中检测中断标记

在线程中处理中断信号最常见的方式是不断地检查中断标记,一旦标记为true,就立即结束线程。

public class MyThread extends Thread {
    public void run() {
        while(!isInterrupted()) {
            // do something
        }
    }
}

上面的代码中,线程不断地执行某个任务,同时在每次循环开始时检查中断标记,如果标记为true,则立即退出线程。如果不检查中断标记,那么线程将不会被停止。

2. 在sleep、wait等阻塞方法中捕获中断异常

在使用阻塞方法(如sleep、wait等)时,也可以使用中断机制停止线程。当线程处于sleep、wait等阻塞状态时,调用线程的interrupt()方法将会导致线程抛出InterruptedException异常,从而使线程提前退出阻塞状态。

public class MyThread extends Thread {
    public void run() {
        try {
            while(!isInterrupted()) {
                // do something
                Thread.sleep(1000); // 使用阻塞方法
            }
        } catch (InterruptedException e) {
            // 处理中断异常
        }
    }
}

上面的代码中,线程在循环过程中使用了sleep阻塞方法。由于线程处于阻塞状态,无法在循环中检查中断标记。因此,当线程收到中断信号时,会抛出InterruptedException异常,从而使线程提前退出阻塞状态,进而继续执行线程中的循环所在位置的代码。需要注意的是,抛出InterruptedException异常也清除线程的中断状态。

示例说明

示例一

public class ThreadInterruptDemo {
    public static void main(String[] args) throws InterruptedException {
        Thread t = new Thread(new Runnable() {
            @Override
            public void run() {
                while (!Thread.currentThread().isInterrupted()) {
                    System.out.println("线程正在运行...");
                    try {
                        Thread.sleep(1000);
                    } catch (InterruptedException e) {
                        break;
                    }
                }
                System.out.println("线程结束");
            }
        });
        t.start();

        Thread.sleep(5000);
        t.interrupt();
    }
}

上述示例中,主线程创建了一个新线程t,并启动该线程。在新线程t中使用while循环不断输出一行“线程正在运行…”,并使用Thread.sleep()方法暂停1秒钟,从而模拟线程正在工作。

在主线程休眠5秒钟后,调用新线程t的interrupt()方法,线程t会收到中断信号,终止循环并输出“线程结束”。这说明通过使用中断机制,能够实现对线程的安全停止。

示例二

public class ThreadInterrupt2Demo {
    public static void main(String[] args) throws InterruptedException {
        ThreadCounter counter = new ThreadCounter();
        Thread t1 = new Thread(counter, "Thread-1");
        Thread t2 = new Thread(counter, "Thread-2");
        t1.start();
        t2.start();

        Thread.sleep(5000);
        t1.interrupt();
        t2.interrupt();
    }

    private static class ThreadCounter implements Runnable {
        @Override
        public void run() {
            int count = 0;
            while (!Thread.currentThread().isInterrupted() && count < 5) {
                count++;
                System.out.println(Thread.currentThread().getName() + ": " + count);
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    Thread.currentThread().interrupt(); // 重新设置中断标志
                }
            }
            System.out.println(Thread.currentThread().getName() + "结束");
        }
    }
}

上述示例中,主线程创建了两个新线程t1和t2,并启动这两个线程。线程t1和t2都执行一个Runnable接口实现类ThreadCounter的代码逻辑,主要是在循环中不断输出线程名称和计数器的数值,并使用Thread.sleep()方法暂停1秒钟,从而模拟线程正在工作,计数器的默认初始值为0。

在主线程休眠5秒钟后,调用线程t1和t2的interrupt()方法,线程t1和t2将会收到中断信号,并尝试重新设置自己的中断标记,从而安全终止循环输出线程结束信息。

需要注意的是,由于在线程t1和t2中捕获InterruptedException异常而重新设置中断标记,因此在重新设置中断标记后,循环中使用Thread.sleep()方法时就可能再次触发InterruptedException异常,所以需要再次调用interrupt()方法来设置自己的中断标记。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:java中使用interrupt通知线程停止详析 - Python技术站

(0)
上一篇 2023年5月25日
下一篇 2023年5月25日

相关文章

  • Spring MVC 4.1.3 + MyBatis零基础搭建Web开发框架(注解模式)

    下面是Spring MVC 4.1.3 + MyBatis零基础搭建Web开发框架(注解模式)的完整攻略。 1. 环境搭建 JDK安装及环境变量配置 Maven安装及配置 Eclipse/IDEA集成Maven插件及配置 2. 项目建立 利用Maven建立项目:新建Maven项目,设置GroupId、ArtifactId、Version等基本信息。 导入相关…

    Java 2023年5月31日
    00
  • 深入研究spring boot集成kafka之spring-kafka底层原理

    深入研究Spring Boot集成Kafka之Spring Kafka底层原理的攻略如下: 一、关于Spring Kafka Spring Kafka是Spring项目组为了在Spring项目中集成Kafka而研发的一个库,它基于Kafka提供了高度抽象的API, 并与Spring框架完美集成,提供了非常方便的方式用于实现Kafka的生产和消费。 二、Spr…

    Java 2023年6月2日
    00
  • 入门java的第一步HelloWorld

    下面是“入门Java的第一步HelloWorld”的完整攻略: 步骤一:安装Java开发工具 在进行Java编程前,需要安装Java开发工具,例如Eclipse、NetBeans等。本文以Eclipse为例进行讲解。 Eclipse下载地址:https://www.eclipse.org/downloads/ 下载后双击exe文件进行安装,安装完成后启动Ec…

    Java 2023年5月19日
    00
  • 利用Java获取文件名、类名、方法名和行号的方法小结

    下面我来详细讲解一下“利用Java获取文件名、类名、方法名和行号的方法小结”的完整攻略。 获取文件名、类名、方法名和行号攻略 在Java开发中,我们有时候需要获取当前文件名、类名、方法名和行号等信息,以便于进行调试和日志输出等操作。下面是具体的获取方法: 获取文件名 获取当前文件名可以使用File类中的方法,具体代码如下: File file = new F…

    Java 2023年5月31日
    00
  • 详解Java中的防抖和节流

    Title: 详解Java中的防抖和节流 防抖和节流是前端开发中常用的优化方式,可以避免用户输入事件过于频繁导致页面性能下降。在Java开发中,同样可以使用这两种技术进行优化。 什么是防抖和节流 防抖 防抖是指在用户进行操作时,只有停止操作一段时间后才会触发事件并进行相应操作。这种方式可以避免用户频繁地触发事件导致页面反应缓慢,同时也可以避免一些不必要的重复…

    Java 2023年5月26日
    00
  • SpringBoot FreeWorker模板技术解析

    SpringBoot FreeMarker模板技术解析 什么是FreeMarker模板引擎 FreeMarker是一款基于模板的Java模板引擎,它可以将模板和数据混合在一起生成输出文本,常用于动态生成HTML,XML,电子邮件等文本。 FreeMarker的特点: 容易创建和维护模板 可以产生非常多的输出格式(HTML,XML,XHTML,PDF等等) 可…

    Java 2023年5月19日
    00
  • mybatis动态sql之Map参数的讲解

    Mybatis动态SQL之Map参数的讲解 在Mybatis的Mapper.xml文件中,我们可以使用动态SQL语句,来根据不同的参数值生成不同的SQL,这使得SQL编写更加具有灵活性。其中,Map类型的参数也可以用于动态SQL语句中,接下来将一一讲解这些内容。 1. Map参数的基本使用 我们可以在Mapper.xml中,使用Map类型的参数来实现条件查询…

    Java 2023年5月20日
    00
  • Java反射机制介绍

    Java反射机制介绍 什么是反射机制 Java反射机制是指在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;并能够调用任意一个方法和访问任意一个属性,这种动态获取信息以及动态调用对象的方法的功能称为Java反射机制。 反射机制的优缺点 反射机制非常强大且灵活,但也有一些缺点: 性能问题:反射调用方法的效率要比直接调用方法的效率低很多,所以在需要…

    Java 2023年5月26日
    00
合作推广
合作推广
分享本页
返回顶部