jar 退出run_Java终止线程的三种方式

停止一个线程通常意味着在线程处理任务完成之前停掉正在做的操作,也就是放弃当前的操作。

在 Java 中有以下 3 种方法可以终止正在运行的线程:

使用退出标志,使线程正常退出,也就是当 run() 方法完成后线程中止。

使用 stop() 方法强行终止线程,但是不推荐使用这个方法,该方法已被弃用。

使用 interrupt 方法中断线程。

1. 使用标志位终止线程

在 run() 方法执行完毕后,该线程就终止了。但是在某些特殊的情况下,run() 方法会被一直执行;比如在服务端程序中可能会使用 while(true) { ... } 这样的循环结构来不断的接收来自客户端的请求。此时就可以用修改标志位的方式来结束 run() 方法。

public class ServerThread extends Thread {

//volatile修饰符用来保证其它线程读取的总是该变量的最新的值

public volatile boolean exit = false;

@Override

public void run() {

ServerSocket serverSocket = new ServerSocket(8080);

while(!exit){

serverSocket.accept(); //阻塞等待客户端消息

...

}

}

public static void main(String[] args) {

ServerThread t = new ServerThread();

t.start();

...

t.exit = true; //修改标志位,退出线程

}

}

2. 使用 stop() 终止线程

通过查看 JDK 的 API,我们会看到 java.lang.Thread 类型提供了一系列的方法如 start()、stop()、resume()、suspend()、destory()等方法来管理线程。但是除了 start() 之外,其它几个方法都被声名为已过时(deprecated)。

虽然 stop() 方法确实可以停止一个正在运行的线程,但是这个方法是不安全的,而且该方法已被弃用,最好不要使用它。

JDK 文档中还引入用一篇文章来解释了弃用这些方法的原因:《Why are Thread.stop, Thread.suspend and Thread.resume Deprecated?》

为什么弃用stop:

调用 stop() 方法会立刻停止 run() 方法中剩余的全部工作,包括在 catch 或 finally 语句中的,并抛出ThreadDeath异常(通常情况下此异常不需要显示的捕获),因此可能会导致一些清理性的工作的得不到完成,如文件,数据库等的关闭。

调用 stop() 方法会立即释放该线程所持有的所有的锁,导致数据得不到同步,出现数据不一致的问题。

例如,存在一个对象 u 持有 ID 和 NAME 两个字段,假如写入线程在写对象的过程中,只完成了对 ID 的赋值,但没来得及为 NAME 赋值,就被 stop() 导致锁被释放,那么当读取线程得到锁之后再去读取对象 u 的 ID 和 Name 时,就会出现数据不一致的问题,如下图:

3. 使用 interrupt() 中断线程

现在我们知道了使用 stop() 方式停止线程是非常不安全的方式,那么我们应该使用什么方法来停止线程呢?答案就是使用 interrupt() 方法来中断线程。

需要明确的一点的是:interrupt() 方法并不像在 for 循环语句中使用 break 语句那样干脆,马上就停止循环。调用 interrupt() 方法仅仅是在当前线程中打一个停止的标记,并不是真的停止线程。

也就是说,线程中断并不会立即终止线程,而是通知目标线程,有人希望你终止。至于目标线程收到通知后会如何处理,则完全由目标线程自行决定。这一点很重要,如果中断后,线程立即无条件退出,那么我们又会遇到 stop() 方法的老问题。

事实上,如果一个线程不能被 interrupt,那么 stop 方法也不会起作用。

我们来看一个使用 interrupt() 的例子:

public class InterruptThread1 extends Thread{

public static void main(String[] args) {

try {

InterruptThread1 t = new InterruptThread1();

t.start();

Thread.sleep(200);

t.interrupt();

} catch (InterruptedException e) {

e.printStackTrace();

}

}

@Override

public void run() {

super.run();

for(int i = 0; i <= 200000; i++) {

System.out.println("i=" + i);

}

}

}

输出:

从输出的结果我们会发现 interrupt 方法并没有停止线程 t 中的处理逻辑,也就是说即使 t 线程被设置为了中断状态,但是这个中断并不会起作用,那么该如何停止线程呢?

这就需要使用到另外两个与线程中断有关的方法了:

public boolean Thread.isInterrupted() //判断是否被中断

public static boolean Thread.interrupted() //判断是否被中断,并清除当前中断状态

这两个方法使得当前线程能够感知到是否被中断了(通过检查标志位)。

所以如果希望线程 t 在中断后停止,就必须先判断是否被中断,并为它增加相应的中断处理代码:

@Override

public void run() {

super.run();

for(int i = 0; i <= 200000; i++) {

//判断是否被中断

if(Thread.currentThread().isInterrupted()){

//处理中断逻辑

break;

}

System.out.println("i=" + i);

}

}

输出结果,for 循环在执行完成前就提前结束了:

在上面这段代码中,我们增加了 Thread.isInterrupted() 来判断当前线程是否被中断了,如果是,则退出 for 循环,结束线程。

这种方式看起来与之前介绍的“使用标志位终止线程”非常类似,但是在遇到 sleep() 或者 wait() 这样的操作,我们只能通过中断来处理了。

public static native void sleep(long millis) throws InterruptedException

Thread.sleep() 方法会抛出一个 InterruptedException 异常,当线程被 sleep() 休眠时,如果被中断,这会就抛出这个异常。

(注意:Thread.sleep() 方法由于中断而抛出的异常,是会清除中断标记的。)

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/436875.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【转】人工智能教程-前言

前言 大家好&#xff01;欢迎来到我的网站&#xff01; 人工智能被认为是一种拯救世界、终结世界的技术。毋庸置疑&#xff0c;人工智能时代就要来临了&#xff0c;科幻电影中的场景将成为现实&#xff0c;未来已来&#xff01; 我很庆幸。十四年前就认定了人工智能专业&…

golang 包含 数组_Golang数组类型

数组数组是指一系列同一类型数据的集合。数组中包含的每个数据被称为数组元素(element)&#xff0c;一个数组包含的元素个数被称为数组的长度。1. 声明方法[32]byte //长度为32的数组[2*N] struct {x, y int32} //复杂类型数组[100]*float64 //指针数组[3][5]int //二维数组[2]…

【转】人工智能-1.1.1 什么是神经网络

1.1.1 什么是神经网络 什么是人工智能&#xff1f;通俗来讲&#xff0c;就是让机器能像人一样思考。这个无需解释太多&#xff0c;因为通过各种科幻电影我们已经对人工智能很熟悉了。大家现在感兴趣的应该是——如何实现人工智能&#xff1f; 从1956年夏季首次提出“人工智能…

【V4L2】学习资料

预备知识 V4L2&#xff0c;即Linux视频设备内核驱动。 参考文章 v4l2的学习建议和流程解析Linux V4L2学习高通msm-V4L2-Camera驱动浅析5-buffer00_video_decode (video decode)&#xff1a;此内容为英伟达Jetson的Demo文档手册&#xff0c;有条件的可以结合Jetson的代码阅读…

解决margin塌陷的问题_解决margin塌陷与margin合并(margin)清除浮动问题

**1、margin塌陷**问题&#xff1a;垂直方向的父子关系的盒子使用不当会产生margin塌陷。给子级设置margin-top时&#xff0c;他不会相对父级一起动&#xff0c;只有他的margin超过父级的margin时&#xff0c;才会生效&#xff0c;但会带着父级一起动(作者总结&#xff0c;官方…

【转】人工智能-1.2.2 神经网络是如何进行预测的

上一篇文章中我们已经知道了如何将数据输入到神经网络中。那么神经网络是如何根据这些数据进行预测的呢&#xff1f;我们将一张图片输入到神经网络中&#xff0c;神经网络是如何预测这张图中是否有猫的呢&#xff1f;&#xff1f; 这个预测的过程其实只是基于一个简单的公式&a…

js 根据公历日期 算出农历_一招教会你公历换算成农历,要不要试试看

古代的历法是干支纪年&#xff0c;俗称农历或阴历&#xff0c;现在我们都统一采用公历的阿拉伯数字纪年。因此&#xff0c;就存在着一个历法的换算问题。当然&#xff0c;我们可以查历书就直接知道了&#xff0c;但是这个方法并不一定方便。现在告诉大家一个简单的口诀&#xf…

【转】C# HMAC Sha1 生成签字

最近因为工作的需要&#xff0c;开始接触腾讯云&#xff0c;在调用CMQ服务时发现官方提供的SDK只有基于.Net Framework的&#xff0c;而现在做.net项目的谁不是用.net core啊。好吧&#xff0c;既然没有官方的SDK&#xff0c;只能自己写服务来调用Api了。遇到的第一个麻烦点的事…

去哪查阅RFC文档?

什么是RFC文档 RFC。 Request For Comments&#xff08;RFC&#xff09;&#xff0c;是一系列以编号排定的文件。文件收集了有关互联网相关信息&#xff0c;以及UNIX和互联网社区的软件文件。目前RFC文件是由Internet Society&#xff08;ISOC&#xff09;赞助发行。基本的互联…

【转】Power Platform(简介)

Power Platform 系统通过允许用户执行以下三个关键操作来帮助他们推动业务发展&#xff1a;使用 Power BI 从数据中获得见解&#xff0c;通过使用 PowerApps 构建的应用程序来推动智能业务流程&#xff0c;以及使用 Power Automate 自动执行这些流程。 这些解决方案彼此配合协作…

云原生的本质_CloudNative

[TOC]阿里云原生技术公开课第1章&#xff1a;云原生课本节课程要点云原生技术发展历程(为什么要学习这门课)课程简介与预备知识(这门课到底教什么)云原生的定义与技术要点(本节正式内容)一、为什么要开设云原生技术公开课&#xff1f;1. 云原生技术发展简史首先从第一个问题进行…

【Python】打包程序后运行程序出现 ModuleNotFoundError: No module named ‘PySide6‘

问题描述 在python虚拟环境中使用PySide6开发桌面程序&#xff0c;执行打包命令&#xff1a; pyinstaller.exe -F -w .\main.py 打包程序完成后&#xff0c;双击运行&#xff0c;弹出对话框提示&#xff1a; ModuleNotFoundError: No module named ‘PySide6’ 原因 虚拟环境…

【转】人工智能-1.2.1 如何将数据输入到神经网络中

1.2.1 如何将数据输入到神经网络中 通过对前面文章的学习&#xff0c;我们已经知道神经网络可以实现真正的人工智能。本小节我会进行详细地讲解&#xff0c;让大家彻底地弄懂神经网络。在仅仅只学完一篇文章后&#xff0c;你肯定依然感觉朦胧&#xff0c;这是正常的&#xff0…

php对接钉钉_php实现钉钉业务报警机器人

使用场景&#xff0c;服务器报异常错误&#xff0c;想要及时收到报警信息并处理环境介绍&#xff0c;本博使用yaf框架php&#xff0c;仅仅提供思路&#xff0c;参考&#xff0c;具体根据自己实际情况进行编写1&#xff0c;每十分钟执行一次任务脚本# 每10分钟执行一次的任务if …

【转】30 岁前实现财务自由的人,都做对了哪些事?

不光是30岁&#xff0c;凡是能实现财务自由的&#xff0c;都有一个特点&#xff0c;这个特点叫做&#xff1a; 做庄思维。 在出现近现代法制社会之前&#xff0c;财富的原始积累最快的方式总结起来说到底都是“抢”和“骗”&#xff0c;然后既得利益者为了保护自己的胜利果实…

protobuf2和3同时安装_在 Ubuntu 上安装 Protobuf 3 的教程详解

什么时候需要安装如果使用 protoc 命令&#xff0c;遇到 Protoc not found&#xff0c;表示未安装。或者&#xff0c;执行时出现错误&#xff1a;This parser only recognizes "proto2"&#xff0c;则表示不是3.0版。安装过程及可能遇到的问题安装指令详细介绍请参考…

【转】WPF中关于样式和模板的区别

1.WPF样式 类似于Web应用程序中的CSS&#xff0c;在WPF中可以为控件定义统一的样式(Style)。样式属于资源的一种&#xff0c;例如为Button定义统一的背景颜色和字体&#xff1a; <Window.Resources> <Style TargetType"Button"> <Setter Property&quo…

Qt实现多屏幕多分辨率自适应

这里仅大概描述一下实现思路。 运行条件 两个屏幕&#xff0c;分辨率不同。Qt软件 问题提出 前段时间写了一个软件&#xff0c;窗口内有自绘内容。 自绘内容里面用的长度单位都是像素。可想而知&#xff0c;在开发者的电脑屏幕上大小都是符合要求的。到这一步都没问题。 软…

您需要来自pc的权限才能_微信电脑版还是鸡肋吗?微信PC版3.0内测体验

[PConline 应用]微信PC版3.0来了&#xff01;这到底是个怎样的版本&#xff1f;先说结果吧&#xff0c;好消息是微信PC端新版很快就要上线了&#xff0c;坏消息是这一回采用是邀请内测制&#xff0c;注定了很多人只能等到正式上线后&#xff0c;才能见到新版本&#xff01;目前…

【转】【MySQL】事务与锁(四):行锁到底锁住的是什么?记录?字段?索引?

首先我们有三张表t1,t2,t3&#xff0c;它们都是只有两个字段&#xff0c; int类型的id和varchar类型的name&#xff1b;区别是t1没有索引&#xff0c;t2有主键索引&#xff0c;t3有唯一索引。 再强调一次&#xff0c;在实验前必须提前关闭自动提交&#xff0c;set autocommitof…