首页 > 编程语言 >Java并发编程 interrupt()方法

Java并发编程 interrupt()方法

时间:2023-06-09 16:01:22浏览次数:57  
标签:Java Thread 编程 t1 线程 打断 interrupt java sleep

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,Thread,编程,t1,线程,打断,interrupt,java,sleep
From: https://www.cnblogs.com/keruanren/p/17469136.html

相关文章

  • 第二节 操作系统和编程语言
    查看conda的配置:cat   .bashrc  在第一次配置后会生成这个隐藏文件。如果以前存在有这个文件,记得删除。condaconfig--getchannels   展示自己配置的源condaconfig--addchannels     添加源 conda导出环境,导入环境condaenv......
  • 实例讲解Flink 流处理程序编程模型
    摘要:在深入了解Flink实时数据处理程序的开发之前,先通过一个简单示例来了解使用Flink的DataStreamAPI构建有状态流应用程序的过程。本文分享自华为云社区《Flink实例:Flink流处理程序编程模型》,作者:TiAmoZhang。在深入了解Flink实时数据处理程序的开发之前,先通过一个简单......
  • JavaScript中的模块化编程
    JavaScript中的模块化编程模块化编程是一种将程序拆分为独立模块的开发方法,每个模块具有明确定义的功能和接口。JavaScript中的模块化编程能够提高代码的可维护性、可重用性和可测试性。本文将详细介绍JavaScript中的模块化概念、几种常见的模块化方案,并提供更多的代码示例。1.......
  • [Java SE] 彻底搞懂Java程序的三大参数配置途径:系统变量与JVM参数(VM Option)/环境变
    0序言一次没搞懂,处处受影响。这个问题属于基础问题,但又经常踩坑,不得不重视一下了。1Java程序动态参数的配置途径:系统变量与JVM参数(VMOption)vs环境变量vs启动程序参数argsIDEA中的配置位置参数使用方式示例代码获取方式系统属性由操作系统、JVM、应用......
  • java(springboot)实现将一个pdf按页码转成多张图片
    以下是一个将PDF转换成JPG格式图片的SpringBoot接口代码:importorg.apache.pdfbox.pdmodel.PDDocument;importorg.apache.pdfbox.rendering.PDFRenderer;importorg.springframework.http.MediaType;importorg.springframework.scheduling.annotation.Async;import......
  • java-基础安装-基础
    1.基本须知jdk我们的java源码程序是只能放在src的蓝色文件夹中,放在别的文件不起作用javac.exe文件javac是jdk中专门用来编译源码的文件java.exe文件启动jvm虚拟机*.class是编译后的字节码文件,一般放在idea项目中橘色的out文件夹中*.java是源码文件是源码文件......
  • java代码输出控制台输出菱形
    privatestaticvoidrhombFuncation(){introw=3;for(inti=1;i<=row;i++){for(introw1=row;row1>i;row1--){System.out.print("-");}for(intj=0;j<i;j++){Syste......
  • 【MCA】Java互联网高级架构师马SB
    【MCA】Java互联网高级架构师马SBdownload:3w51xuebccomRedis核心数据结构实战与高性能原理剖析Redis是一款开源的内存数据库,它提供了丰富的数据结构和API,并支持多种数据类型操作。在深入理解Redis核心数据结构实战和高性能原理之前,我们需要了解以下基础知识:Redis数据结构Redis支......
  • 基于JAVA在线考试系统
    计算机网络技术的成熟,使其在教育领域的应用范围越来越广泛。传统意义的考试方式因其效率低、工作量大、浪费资源等缺陷正面临着重大的变革。 本文所设计的系统在功能上主要有四个方面特点:一是实现题库的录入。教师将试卷上传,系统将内容检索后将试题存入数据库中。利用数据库技术......
  • 图灵Java架构班第六期无密 水晶帘动微风起
    图灵Java架构班第六期无密水晶帘动微风起download:3w51xuebccomRedis核心数据结构实战与高性能原理剖析Redis是一款开源的内存数据库,它提供了丰富的数据结构和API,并支持多种数据类型操作。在深入理解Redis核心数据结构实战和高性能原理之前,我们需要了解以下基础知识:Redis数据结构......