小编给大家分享一下Java多线程之Interrupt中断线程的示例分析,希望大家阅读完这篇文章之后都有所收获,下面让我们一起去探讨吧!
https://gitee.com/zture/spring-test/blob/master/multithreading/src/test/java/cn/diswares/blog/InterruptTests.java
为了方便理解简介中 interrupt 的概念, 写个 DEMO 测试一下
/** * 调用 interrupt 并不会影响线程正常运行 */ @Test public void testInvokeInterrupt() throws InterruptedException { Thread t1 = new Thread(() -> { for (int i = 0; ; i++) { log.info(i + ""); } }); t1.start(); // 确保 t1.start() 成功执行 Thread.sleep(1); log.info("interrupt 前 t1 interrupt 状态 = {}", t1.isInterrupted()); t1.interrupt(); log.info("interrupt 后 t1 interrupt 状态 = {}", t1.isInterrupted()); log.info("t1 是否存活 = {}", t1.isAlive()); }
首先 main 线程中启动 t1线程
t1 线程死循环输出 i++
main 线程确保 t1.start() 执行后
打印 t1 线程的线程中断状态
调用 t1.interrupt() 方法使线程中断
打印 t1 线程的线程中断状态
ignore logs ......
20:29:57.632 [Thread-1] INFO cn.diswares.blog.interrupt.InterruptTests - 2561
20:29:57.633 [Thread-1] INFO cn.diswares.blog.interrupt.InterruptTests - 2562
20:29:57.633 [Thread-1] INFO cn.diswares.blog.interrupt.InterruptTests - 2563
20:29:57.486 [main] INFO cn.diswares.blog.interrupt.InterruptTests - interrupt 前 t1 interrupt 状态 = false
20:29:57.633 [Thread-1] INFO cn.diswares.blog.interrupt.InterruptTests - 2564
20:29:57.633 [Thread-1] INFO cn.diswares.blog.interrupt.InterruptTests - 2565
20:29:57.633 [Thread-1] INFO cn.diswares.blog.interrupt.InterruptTests - 2566
20:29:57.633 [Thread-1] INFO cn.diswares.blog.interrupt.InterruptTests - 2567
20:29:57.633 [Thread-1] INFO cn.diswares.blog.interrupt.InterruptTests - 2568
20:29:57.633 [main] INFO cn.diswares.blog.interrupt.InterruptTests - interrupt 后 t1 interrupt 状态 = true
20:29:57.633 [main] INFO cn.diswares.blog.interrupt.InterruptTests - t1 是否存活 = true
20:29:57.633 [Thread-1] INFO cn.diswares.blog.interrupt.InterruptTests - 2569
20:29:57.633 [Thread-1] INFO cn.diswares.blog.interrupt.InterruptTests - 2570
20:29:57.633 [Thread-1] INFO cn.diswares.blog.interrupt.InterruptTests - 2571
ignore logs ......
现象描述
调用 t1.interrupt() 执行前线程的 interrupt 状态为 false
调用 t1.interrupt() 执行后线程的 interrupt 状态为 true
线程并没有被中断, 可以成功死循环输出循环次数
Interrupt 的真正作用是给线程对象设置一个中断标记, 并不会影响线程的正常运行
new Thread().interrupt()
中断此线程(此线程不一定是当前线程,而是指调用该方法的Thread实例所代表的线程),但实际上只是给线程设置一个中断标志,线程仍会继续运行。
Thread.interrupted()
注意: 这是个静态方法
测试当前线程是否被中断(检查中断标志), 返回一个当前线程的 interrupt 状态, 并重置.
当我们第二次调用时中断状态已经被重置, 将返回一个false
为了方便理解. 写一个 DEMO
DEMO 非常简单, 调用两次 Thread.interrupted() 观察 main 线程的 interrupt 标记
/** * 二次调用 t1.interrupted() */ @Test public void testDoubleInvokeInterrupted () throws InterruptedException { Thread.currentThread().interrupt(); log.info("interrupted1 = {}", Thread.interrupted()); log.info("interrupted2 = {}", Thread.interrupted()); }
输出日志
21:06:33.397 [main] INFO cn.diswares.blog.interrupt.InterruptTests - interrupted1 = true
21:06:33.402 [main] INFO cn.diswares.blog.interrupt.InterruptTests - interrupted2 = false
由于是静态方法. 我们来看一下另一个小程序.
跟之前一样将 t1 程序中断
调用 t1.interrupted()
注意这里是个静态方法
/** * 在主线程中调用 t1.interrupted() */ @Test public void testMainInterrupted() throws InterruptedException { Thread t1 = new Thread(() -> { for (int i = 0; ; i++) { log.info("t1 is live"); } }); t1.start(); Thread.sleep(1); t1.interrupt(); Thread.sleep(1); log.info("{}", t1.interrupted()); }
拓展程序日志
ignore logs ......
21:11:20.504 [Thread-1] INFO cn.diswares.blog.interrupt.InterruptTests - t1 is live
21:11:20.504 [Thread-1] INFO cn.diswares.blog.interrupt.InterruptTests - t1 is live
21:11:20.490 [main] INFO cn.diswares.blog.interrupt.InterruptTests - false
21:11:20.504 [Thread-1] INFO cn.diswares.blog.interrupt.InterruptTests - t1 is live
21:11:20.504 [Thread-1] INFO cn.diswares.blog.interrupt.InterruptTests - t1 is live
21:11:20.504 [Thread-1] INFO cn.diswares.blog.interrupt.InterruptTests - t1 is live
ignore logs ......
拓展程序结论
Thread.interrupted() 方法是静态方法
它的实现为 Thread.currentThread(), 获取的是当前正在执行的线程, JDK 原文注释如下
Returns a reference to the currently executing thread object.
Returns: the currently executing thread.
所以这里 t1.interrupted() 返回的其实是 main 线程的线程中断标记
new Thread().isInterrupted()
返回线程对象的中断标记, 不会改变中断标记
true: 中断标记存在
false: 未设置中断标记状态
优雅的结束一个线程
在 Java 中结束一个线程一般有下面三种手段:
(禁用) Thread.stop() 这个方法已经被废弃. 因为这种结束线程的方式过于暴力. 会将当前线程暴力终结. 同时线程持有的锁也都会释放, 并且用户有任何额外的处理来控制, 会导致数据不一致
volatile: 外部申明 volatile 开关变量, 当开关条件不满足时结束
(推荐) interrupt: 最优雅的方案
最初的 DEMO 是个死循环, 那我们对其改造一下. 让它能够优雅的结束
/** * 调用 interrupt 并不会影响线程正常运行 */ @Test public void testGracefulEndThread() throws InterruptedException { Thread t1 = new Thread(() -> { for (int i = 0; ; i++) { if (Thread.currentThread().isInterrupted()) { log.info("{} = true, i = {}", Thread.currentThread().getName(), i); break; } else { log.info("{} = false, i = {}", Thread.currentThread().getName(), i); } } }); t1.start(); // 确保 t1.start() 成功执行 TimeUnit.SECONDS.sleep(1); t1.interrupt(); TimeUnit.SECONDS.sleep(1); log.info(t1.getState().toString()); }
1. 简单,只需理解基本的概念,就可以编写适合于各种情况的应用程序;2. 面向对象;3. 分布性,Java是面向网络的语言;4. 鲁棒性,java提供自动垃圾收集来进行内存管理,防止程序员在管理内存时容易产生的错误。;5. 安全性,用于网络、分布环境下的Java必须防止病毒的入侵。6. 体系结构中立,只要安装了Java运行时系统,就可在任意处理器上运行。7. 可移植性,Java可以方便地移植到网络上的不同机器。8.解释执行,Java解释器直接对Java字节码进行解释执行。
看完了这篇文章,相信你对“Java多线程之Interrupt中断线程的示例分析”有了一定的了解,如果想了解更多相关知识,欢迎关注亿速云行业资讯频道,感谢各位的阅读!
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。