Java学习-082-多线程15:线程中断退出

查看上篇文章的源代码执行结果,可以发现,在中断线程后,线程状态并未变化,且线程并未立即停止运行,而是继续运行至结束,输出创建了 800 个文件。

查看 Thread.interrupt() 源代码可知,interrupt() 中断线程方法,仅设置线程的中断标志位为 true 并立即返回,并未改变线程运行状态。源代码如下所示:

 

 

通过 isInterrupted() 方法,可以查看当前线程是否被中断,进而通过代码逻辑控制决定是否停止线程操作。isInterrupted() 源代码如下所示。

 

 

通过 interrupted()  方法,也可查看当前线程是否被中断,进而通过代码逻辑逻辑实现业务需求。但与 isInterrupted()  不同的是,interrupted() 该方法发现线程中断后会清空线程中断标志。 

 

 

因而,在判定线程是否被中断时,推荐使用 isInterrupted() 方法。

使用 isInterrupted()  方法处理线程被中断后的业务操作逻辑实现代码如下所示:

package com.fanfengping.demo;

import lombok.extern.slf4j.Slf4j;

import java.io.*;

@Slf4j
public class Demo10RunnableInterruptExit implements Runnable {
    @Override
    public synchronized void run() {
        Thread thread = Thread.currentThread();

        try {
            log.info("t1 >> {} 开始运行", thread.getName());
            log.info("t2 >> {} 运行状态:{},是否存活:{},是否被中断:{}", thread.getName(), thread.getState().name(), thread.isAlive(), thread.isInterrupted());

            log.info("t3 >> {} 开始休眠", thread.getName());
            Thread.sleep(3000);
            log.info("t4 >> {} 结束休眠", thread.getName());

            log.info("t5 >> {} 开始写文件", thread.getName());
            for (int i = 0; i < 800; i++) {
                // 若是线程被中断,则退出线程
                if(!Thread.currentThread().isInterrupted()) {
                    File file=new File("E:/office-new/personal/multi-thread-demo/src/main/resources/files/test-" + i + ".log");
                    if(!file.exists())
                        file.createNewFile();
                    FileOutputStream out = new FileOutputStream(file,true);
                    for(int j=0;j<10000;j++) {
                        StringBuffer sb = new StringBuffer();
                        sb.append("这是第"+i+"行:前面介绍的各种方法都不关用,为什么总是奇怪的问题 ");
                        out.write(sb.toString().getBytes("utf-8"));
                    }
                    out.close();
                } else {
                    break;
                }
            }
            log.info("t6 >> {} 结束写文件", thread.getName());

            log.info("t7 >> {} 开始休眠", thread.getName());
            Thread.sleep(5000);
            log.info("t8 >> {} 结束休眠", thread.getName());
        } catch (InterruptedException | UnsupportedEncodingException e) {
            log.error("t9 >> " + thread.getName() + " 被中断", e);
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public static void main(String[] args) {
        try {
            Demo10RunnableInterruptExit demo10RunnableInterrupt = new Demo10RunnableInterruptExit();

            Thread threadInterrupt = new Thread(demo10RunnableInterrupt, "Interrupt_demo");

            log.info("1 >> {} 运行状态:{},是否存活:{},是否被中断:{}", threadInterrupt.getName(), threadInterrupt.getState().name(), threadInterrupt.isAlive(), threadInterrupt.isInterrupted());

            log.info("2 >> {} 启动线程", threadInterrupt.getName());
            threadInterrupt.start();
            log.info("3 >> 主线程休眠 1 秒");
            Thread.sleep(1000);
            log.info("4 >> {} 运行状态:{},是否存活:{},是否被中断:{}", threadInterrupt.getName(), threadInterrupt.getState().name(), threadInterrupt.isAlive(), threadInterrupt.isInterrupted());

            log.info("5 >> 主线程休眠 7 秒");
            Thread.sleep(7000);
            log.info("6 >> {} 中断线程", threadInterrupt.getName());
            threadInterrupt.interrupt();
            log.info("7 >> 主线程休眠 1 秒");
            Thread.sleep(1000);
            log.info("8 >> {} 运行状态:{},是否存活:{},是否被中断:{}", threadInterrupt.getName(), threadInterrupt.getState().name(), threadInterrupt.isAlive(), threadInterrupt.isInterrupted());

            log.info("9 >> 主线程休眠 18 秒");
            Thread.sleep(18000);
            log.info("10 >> {} 运行状态:{},是否存活:{},是否被中断:{}", threadInterrupt.getName(), threadInterrupt.getState().name(), threadInterrupt.isAlive(), threadInterrupt.isInterrupted());

            log.info("11 >> 主线程休眠 40 秒");
            Thread.sleep(40000);
            log.info("12 >> {} 运行状态:{},是否存活:{},是否被中断:{}", threadInterrupt.getName(), threadInterrupt.getState().name(), threadInterrupt.isAlive(), threadInterrupt.isInterrupted());
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

 执行结果如下图所示:

 

 

在执行业务逻辑代码外围,添加方法判断逻辑控制。执行源代码可以发现,核心业务(创建文件)在线程中断后,停止运行。实际操作中,也可根据实际需求对已处理的业务逻辑进行回滚处理,以保证中断前后数据的一致性。

 

posted @ 2021-07-23 21:11  范丰平  Views(95)  Comments(0Edit  收藏  举报