Java一个线程能否结束另一个永不停止的线程
在Java中停止一个线程有三种办法 :
1.正常结束执行;
2.发生异常;
3.被其他线程stop(Java官方不建议)
参考:https://docs.oracle.com/javase/8/docs/technotes/guides/concurrency/threadPrimitiveDeprecation.html
为什么Thread.stop
弃用?
因为它本质上是不安全的。停止线程会导致它解锁已锁定的所有监视器。(当ThreadDeath
异常传播到堆栈中时,监视器将被解锁。)如果先前受这些监视器保护的任何对象处于不一致状态,则其他线程现在可以以不一致的状态查看这些对象。据说这些物体已被 损坏。当线程对受损对象进行操作时,可能会导致任意行为。这种行为可能很微妙并且难以检测,或者可能是明显的。与其他未经检查的异常不同,它会 ThreadDeath
默默地杀死线程; 因此,用户没有警告他的程序可能被破坏。
所以如果遇到一种特殊情况某一个线程A会一直执行下去停不下来,这种情况是存在的比如那种需要持续取样的线程A,当然了在正常代码里会有“停止”功能,外部线程B可以发送停止信号给A,A可以直接结束。
如果A线程没有这种信号量那么B线程还可以主动停止他么?答案是不可以!
public class Test {public static void main(String args[]) throws InterruptedException {Thread thread1 = new Thread() {public void run() {fun_a();}};thread1.start();int a = 0;while (a < 100) {Thread.sleep(1000);a++;if (a == 3) {a = 100;thread1.interrupt();//thread1.stop();//throw new RuntimeException("主函数抛出异常");}}}public static void fun_a() {for (; ; ) {try {Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}System.out.println(">> " + DateUtil.getNowTimeString());}}
}
可以看到interrupt并不能让运行中的线程停止,这个是很容易被误解的地方。这个方法的作用并不是中断线程,而是设置一个标识,通知该线程可以被中断了,到底是继续执行,还是中断返回,由线程本身自己决定。
当对一个线程调用了interrupt()
之后,如果该线程处于被阻塞状态(比如执行了wait、sleep或join等方法),那么会立即退出阻塞状态,并抛出一个InterruptedException
异常,在代码中catch这个异常进行后续处理。如果线程一直处于运行状态,那么只会把该线程的中断标志设置为 true,仅此而已,所以interrupt()
并不能真正的中断线程,不过在rpc调用的场景中,请求线程一般都处于阻塞状态,等待数据返回,这时interrupt()
方法是可以派上用场的。
参考:Java中如何实现线程的超时中断
修改子线程的代码:
public static void fun_a() {for (; ; ) {try {Thread.sleep(1000);} catch (InterruptedException e) {throw new RuntimeException("子线程抛出异常");//e.printStackTrace();}System.out.println(">> " + DateUtil.getNowTimeString());}}
这次是可以结束子线程,前提是子线程自己有异常捕获机制,可以接受其他线程发来的InterruptedException:
主线程每隔2秒对子线程进行一次Interrupted:
package com.t.www;public class Test {final static Object lock = new Object();volatile boolean stop = false;public static void main(String args[]) throws InterruptedException {Thread thread1 = new Thread() {public void run() {fun_a();}};thread1.start();System.out.println("> 1 主线程start " + DateUtil.getNowTimeString());int a = 0;while (a < 3) {Thread.sleep(2000);a++;System.out.println("> 2 主线程对子线程开始interrupt " + DateUtil.getNowTimeString());thread1.interrupt();System.out.println("> 3 主线程对子线程完成interrupt " + DateUtil.getNowTimeString());}}public static void fun_a() {for (; ; ) {try {System.out.println(">> 1 子线程wait " + DateUtil.getNowTimeString());synchronized (lock) {lock.wait();}Thread.sleep(1000);} catch (InterruptedException e) {//throw new RuntimeException("子线程抛出异常");e.printStackTrace();}System.out.println(">> 2 子线程完成 " + DateUtil.getNowTimeString());}}
}
修改子线程代码:
try {System.out.println(">> 1 子线程wait " + DateUtil.getNowTimeString());synchronized (lock) {lock.wait();}Thread.sleep(1000);} catch (InterruptedException e) {//throw new RuntimeException("子线程抛出异常");//e.printStackTrace();System.out.println(">> 2 子线程捕获异常 " + DateUtil.getNowTimeString());}
从运行结果看和前面一致,只是没有抛出异常。
修改代码子线程使用while(!Thread.currentThread().isInterrupted())判断:
public class Test {public static void main(String args[]) throws InterruptedException {Thread thread1 = new Thread() {public void run() {fun_a();}};thread1.start();System.out.println("> 1 主线程start " + DateUtil.getNowTimeString());int a = 0;while (a < 3) {Thread.sleep(2000);a++;System.out.println("> 2 主线程对子线程开始interrupt " + DateUtil.getNowTimeString());thread1.interrupt();System.out.println("> 3 主线程对子线程完成interrupt " + DateUtil.getNowTimeString());}}public static void fun_a() {while(!Thread.currentThread().isInterrupted()){try {System.out.println(">> 1 子线程 " + DateUtil.getNowTimeString());Thread.sleep(1000);} catch (InterruptedException e) {//throw new RuntimeException("子线程抛出异常");//e.printStackTrace();System.out.println(">> 2 子线程捕获异常 " + DateUtil.getNowTimeString());}System.out.println(">> 3 子线程完成 " + DateUtil.getNowTimeString());}System.out.println(">> 4 子线程正常结束 " + DateUtil.getNowTimeString());}
}
可以看到这次因为子线程增加了状态判断所以可以正常结束:
比较优雅的方式是使用一个变量在线程间通信,需要注意的是要保证可见性:
public class Test {private static volatile boolean finished = false; // ① volatile条件变量public static void main(String args[]) throws InterruptedException {Thread thread1 = new Thread() {public void run() {fun_a();}};thread1.start();System.out.println("> 1 主线程start " + DateUtil.getNowTimeString());int a = 0;while (a < 3) {Thread.sleep(2000);a++;}System.out.println("> 1 主线程 a=" +a+" "+ DateUtil.getNowTimeString());finished=true;}public static void fun_a() {while(!finished){try {System.out.println(">> 1 子线程 " + DateUtil.getNowTimeString());Thread.sleep(1000);} catch (InterruptedException e) {//throw new RuntimeException("子线程抛出异常");//e.printStackTrace();System.out.println(">> 2 子线程捕获异常 " + DateUtil.getNowTimeString());}System.out.println(">> 3 子线程完成 " + DateUtil.getNowTimeString());}System.out.println(">> 4 子线程正常结束 " + DateUtil.getNowTimeString());}
}
------------------
如何停止线程或任务
如何停止一个正在运行的java线程
了解Java中的线程中断
如何在Java中正确停止Thread?
你如何杀死Java中的线程?
如何在运行时停止/终止长时间运行的Java线程?超时 - >取消 - >中断状态
Java - 从不同的类停止线程
https://javaconceptoftheday.com/how-to-stop-a-thread-in-java/
如何超时一个线程
参考《Effective Java 中文版 第3版》
相关文章:

pxe cobbler ipmi bmc
http://blog.csdn.net/xuensong520/article/details/8922926 http://blog.csdn.net/xuensong520/article/details/8915945 http://www.wenzizone.cn/?p408 #执行外部脚本(后置脚本)vi /var/www/cobbler/ks_mirror/config/autoip.sh #创建脚本,自动设置Linux系统静…

广东电大计算机绘图试题,电大计算机绘图期末复习试题及答案参考小抄.doc
电大计算机绘图期末复习试题及答案参考小抄一、填空题(每小题1.5分,共30分)1.CAD的常用图形输入设备有???鼠标??、数字化仪、图形输入板、光笔、??键盘 等。2.CAD的软件可分为系统软件、支撑软件和???应用软件??? 软件三个层次。…

django07 字符串替换
1. 模板语言(字符串替换) 1. 母版和继承 1. 什么时候用母版? html页面有重复的代码,把它们提取出来放到一个单独的html文件。 (比如:导航条和左侧菜单) 2. 子页面如何使用母版? {% e…

【云和恩墨】一次 truncate 核心表衍生的安全管理思考
第一章 一次 truncate 核心表衍生的安全管理思考 云和恩墨 | 2016-05-06 17:56 本文编辑整理来自上周四晚云和恩墨大讲堂 黄嵩 关于数据安全问题的分享。安全问题涉及到信息系统的方方面面,尤其是其核心资产——数据的安全。无论是数据访问控制的裸露࿰…
合理估算线程池线程数量
参考《Java并发编程实战》 线程数量计算公式 公式:Nthread Ncpu * Ucpu * (1 W/C),各字段含义: Nthreads:线程数量 Ncpu:CPU的数量,Runtime.getRuntime().availableProcessors()…

通过regedt查看计算机密码,win10系统通过注册表设置定时更换密码提醒的处理步骤...
有关win10系统通过注册表设置定时更换密码提醒的操作方法想必大家有所耳闻。但是能够对win10系统通过注册表设置定时更换密码提醒进行实际操作的人却不多。其实解决win10系统通过注册表设置定时更换密码提醒的问题也不是难事,小编这里提示两点: 1、首先在…

苏宁零售云 App 稳定保障实践
1. 背景 苏宁零售云目标T4-T6级市场的业务,定位更靠谱的智慧零售解决方案和零售服务集成商,实战式跨界赋能。苏宁易购TO C的经验丰富,相关的方案很完善,但是零售云TO B相关业务启动后,业务增长迅速,App相关…

小酌重构系列[8]——提取接口
前言 世间唯一“不变”的是“变化”本身,这句话同样适用于软件设计和开发。在软件系统中,模块(类、方法)应该依赖于抽象,而不应该依赖于实现。 当需求发生“变化”时,如果模块(类、方法…
多线程并发编程需要注意虚假唤醒Spurious wakeup
虚假唤醒 Spurious wakeup 如果等待线程在没有通知被调用的情况下唤醒,则称为Spurious wakeup。 解决方案就是: 使用while条件判断,更好的方案是避免使用wait这种低级的API,而是使用高级的并发工具。 因为这些高级的并发工具都是经过无数…

高中计算机个人总结怎么写,毕业生自我总结范文
毕业生自我总结范文1时光飞逝,三年忙碌而充实的大学生活在一片有序的繁忙中将要过去了,回首过去三年,内心感慨万千。我是20xx年春参加电大机械班的学习,回顾这三年的电大学习之路,饱含了汗水和收获。总结是一面镜子&am…

python - 字符串的格式化输出
# -*- coding:utf-8 -*-project: jiaxyauthor: Jimmyfile: study_2_str.pyide: PyCharm Community Editiontime: 2018-11-01 15:12blog: https://www.cnblogs.com/gotesting/# 字符串s #空字符串# 1:字符串拼接# 1.1:字符串与字符串的拼接用 连接s_1 hellos_2 worlds_3 5…
一个冷僻的知识点try直接返回finally里的设置null其实无效
先看引用类型的代码: import java.util.HashMap; import java.util.Map;public class trycatchefinally {public static void main(String[] args) {System.out.println(getMap().get("KEY"));}public static Map<String, String> getMap() {Map&l…

身份证工具类
2019独角兽企业重金招聘Python工程师标准>>> 身份证工具类 package com.pqs.common.tools;import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.Calendar; import java.util.Date; import java.util.HashMap; import java.util…

目前常用的服务器端网络操作系统有,目前常用的服务器端网络操作系统是()。...
在一台IP地址为192.168.1.1的Windows Server 2008 R2计算机上安装活动目录,建立一个森林根域test.com,保留默认的域功能级别,同时使该计算机成为域test.com的首台域控制器并承担着DNS服务器和全局编录服务器的角色。 操作步骤ÿ…

如何处理用代码创建SD Sales order时遇到的错误消息KI 180
2019独角兽企业重金招聘Python工程师标准>>> 错误消息KI 180:You must enter a company code for transaction Create sales document 代码: REPORT zcreate_so.DATA: ls_header TYPE bapisdhd1,ls_headerx TYPE bapisdhd1x,lt_bapiret2 LIKE bapiret2 OCCURS …
Flink 基本原理与生产实践分享【入门必读,概念清晰】
Flink 基本原理与生产实践分享【入门必读,概念清晰】 https://zh.wikipedia.org/zh-hans/Apache_Flink Apache Flink是由Apache软件基金会开发的开源流处理框架,其核心是用Java和Scala编写的分布式流数据流引擎。Flink以数据并行和流水线方式执行任意流…

数据库模型设计——主键的设计
在数据库设计时,主要就是对实体和关系的设计,实体表现出来就是表,关系表现出来就是外键。而对于一个表,由两部分组成:主键和属性。主键的简单定义就是表中为每一行数据的唯一标识。其实更准确的说法,每一行…

jsp ajax动态添加数据,jquery Ajax实现Select动态添加数据
jquery Ajax实现Select动态添加数据,具体内容如下1.背景最近在工作中,遇到了一个关于select的问题。一般情况下,select下拉框中的数据都是固定的或者直接在jsp中读取列表值显示。但是,这次要实现select与别的选项框联动࿰…

Spring Boot(十一)Redis集成从Docker安装到分布式Session共享
2019独角兽企业重金招聘Python工程师标准>>> 一、简介 Redis是一个开源的使用ANSI C语言编写、支持网络、可基于内存亦可持久化的日志型、Key-Value数据库,并提供多种语言的API,Redis也是技术领域使用最为广泛的存储中间件,它是「…
Java线上问题排障:Linux内核bug引发JVM死锁导致线程假死
Java本质上还是离不开操作系统,一来Java源码是用C/C实现的,二来java进程还是需要依附于操作系统和硬件资源,有时候一些问题是操作系统级别导致的,下面的整个事件是源自一则真实的线上案例。 过程: JVM死锁导致线程不可…

从AdventureWorks学习数据库建模——保留历史数据
在业务需求中,经常需要我们在系统中能够记录历史信息,能够查看到历史变动情况,这时我们可以通过增加开始结束时间字段来记录数据的历史版本。对数据的历史记录主要分为:关系、属性历史,实体历史和变更历史。 关系、属性…

因特网的域名服务器系统的好处,dns域名服务器的作用是什么
大家好,我是智能客服时间君,上述问题将由我为大家进行解答。dns是域名系统 (Domain Name System) 的缩写,该系统用于命名组织到域层次结构中的计算机和网络服务。DNS 命名用于Internet等TCP/IP网络中,通过用户友好的名称查找计算机…

Openssl私建CA
构建私有CA: 在确定配置为CA的服务上生成一个自签证书,并为CA提供所需要的目录及文件即可;步骤: (1) 生成私钥;[rootcentos7 ~]# (umask 077; openssl genrsa -out /etc/pki/CA/private/cakey.pem 4096)Generating RSA priva…
不同版本浏览器前端标准兼容性对照表以及CORS解决跨域和CSRF安全问题解决方案
CORS也已经成为主流的跨域解决方案,不过CORF也会引发CSRF,本文先分享第三方的一个前端工具箱全面展示那些浏览器版本支持CORS,由于各家浏览器厂商因为各自原因在不同的版本里支持的标准不同,这个工具小而美,可以清晰的…

arm服务器获取文件路径中文,ssh 访问远程服务器文件路径
ssh 访问远程服务器文件路径 内容精选换一换在IntelliJ上选择“项目”,找到“.idea”文件夹,单击右键选择“新建>文件”, 输入文件名“settings.json”生成settings.json文件。如图1所示。复制以下代码至新创建的settings.json文件中&…

[Win7]如何还原[.bat]文件关联
2019独角兽企业重金招聘Python工程师标准>>> 此文已迁移到微信公众号:灰灰的Rom笔记,公众号ID:SXF-Rom。 灰灰的Rom笔记 转载于:https://my.oschina.net/shawnxia/blog/672371

Android Monkey使用
Monkey 是什么? Android SDK自带的压力测试工具,也是一个命令行工具。它向系统发送伪随机的用户事件流(如按键输入,触摸屏输入,手势输入等),实现对正在开发的应用程序进行压力测试。 ࿰…
Flink在美团的应用与实践听课笔记
本文系《Flink在美团的应用与实践》的听课笔记 原始视频视频资源已经在优酷公开:2018.8.11 Flink China Meetup北京站-Flink在美团的应用与实践 作者:刘迪珊美团 1.现状和背景 实时平台架构 最底层是数据缓存层,可以看到美团测的所有日志类…

[LeetCode]题解(python):150-Evaluate Reverse Polish Notation
题目来源: https://leetcode.com/problems/evaluate-reverse-polish-notation/ 题意分析: 给定一个数组,用这个数组来表示加减乘除,例如 ["2", "1", "", "3", "*"] -> ((2 …

微软苹果服务器宕机,苹果服务器宕机,iPhone用户别做这两项操作,微软特斯拉也中招...
原标题:苹果服务器宕机,iPhone用户别做这两项操作,微软特斯拉也中招虽然苹果一直都以安全来标榜自己,而事实上也确实如此。IOS封闭的环境,相对与安卓这个开放的环境确实要更加安全一些。苹果可以很好的抵御外来的风险&…