查看上篇文章的源代码执行结果,可以发现,在中断线程后,线程状态并未变化,且线程并未立即停止运行,而是继续运行至结束,输出创建了 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(); } } }
执行结果如下图所示:
在执行业务逻辑代码外围,添加方法判断逻辑控制。执行源代码可以发现,核心业务(创建文件)在线程中断后,停止运行。实际操作中,也可根据实际需求对已处理的业务逻辑进行回滚处理,以保证中断前后数据的一致性。