java 切换主线程_Java线程状态及切换、关闭线程的正确姿势分享

前言

在讲线程之前有必要讨论一下进程的定义:进程是程序在一个数据集合上运行的过程,它是系统进行资源分配和调度的一个独立单位。进程实体由程序段, 数据段 PCB(进程控制块)组成。线程又是什么?线程可以看做轻量级进程,线程是进程的执行单元,是进程调度的基本单位

本文将详细介绍关于Java线程状态及切换、关闭线程的相关内容,下面话不多说了,来一起看看详细的介绍吧

1、线程状态及切换

Java中的线程有六种状态,使用线程Thread内的枚举类来实现,如下,我对每个状态都进行了一定的解释。

public enum State {

/** 表示一个线程还没启用(即未调用start方法)*/

NEW,

/**

* JVM中执行的线程都是处于这个状态的,但是处于这个状态不一定在JVM中执行,

* 也就是说,只有这个状态有资格被JVM调度从而获得时间片执行。

*/

RUNNABLE,

/**

* 线程在等待获取锁资源从而进入阻塞状态,

* 在这个状态中,其一直监视锁的动态,随时准备抢占锁

* 若获得锁资源,重新进入RUNNABLE状态

*/

BLOCKED,

/**

* 当调用Object.wait、Thread.join或者LockSupport类的park方法的时候,线程进入此状态,

* 该状态若无其他线程主动唤醒,则无期限的等待。

* 唤醒的方法包括:Object.notify(唤醒随机一个)、Object.notifyAll(唤醒全部线程),

* 被唤醒的线程重新进入RUNNABLE状态

*/

WAITING,

/**

* 同WAITING状态,不过不同的是调用的方法加上了时间的限制,

* 例如:Object.wait(10)、Thread.sleep(10)、Thread.join(10)、LockSupport.parkNanos(10)、LockSupport.parkUntil(10)这些方法

* 唤醒的方法有两种:

* 1、时间过期。

* 2、其他线程调用了notify或者notifyAll

* 唤醒之后同样进入RUNNABLE状态

*/

TIMED_WAITING,

/** 线程的终点(正常死亡或者被终止)*/

TERMINATED;

}

除了NEW和TERMINATED之外,其他的状态都是可以相互转换的,其转换过程如下图所示

这里特别讲一下RUNNABLE状态,在这个状态中线程并不一定在执行程序,只有被JVM调度的线程才能获得执行的时间片,并且只有这个状态的线程才能够获得时间片,换句话说,被JVM调度并且获得时间片是只属于处于RUNNABLE状态线程的权利。为了便于理解,可以将RUNNABLE分成Runnable和Running两个状态(当然,你也可以换成其他的,这里我只是自己好理解),那么上面的线程转换图就转变成了下面这样(参考《Java并发编程的艺术》中的线程状态图):

关于线程状态转换的例子,可以通过下面的代码加深理解

public class Test {

public static void main(String[] args) {

Test test = new Test();

// 1.NEW状态

Thread thread = new Thread(() -> {

// 3.进行test对象锁的争夺,若抢到锁则继续执行,否则进入BLOCKED状态监控该锁,重新获得后进入RUNNABLE

synchronized (test) {

try {

// 4.进入TIMED_WAITING状态,100ms后重新进入RUNNABLE状态争夺时间片

Thread.sleep(100);

// 5.重新获得时间片之后,进入WAITING状态

test.wait();

} catch (InterruptedException e) {

e.printStackTrace();

}

}

// 6.正常run()方法执行完毕后线程结束,进入TERMINATED

});

// 2.调用start()方法,线程进入RUNNABLE状态

thread.start();

}

}

注:代码执行的顺序为注释的序号

2、正确的结束一个线程

在上面的例子中我们看到线程的run方法正常执行完毕之后线程就正常死亡进入TERMINATED状态了,那么如果我们有中途停止线程的需求,我们应该如何正确的结束一个线程呢?

使用interrupt()方法:在线程内部,其定义了一个变量来标识当前线程是否处于被打断状态,调用interrupt()方法则使这个状态变为true。我们采用这个方法加异常处理的方式来结束一个线程。

public static void main(String[] args) {

Thread thread = new Thread(() -> {

try {

Thread.sleep(1);

} catch (InterruptedException e) {

e.printStackTrace();

// 这里的return是必须的,原因后面说明

return;

}

System.err.println("thread interrupt test...");

});

thread.start();

thread.interrupt();

System.out.println("main thread end...");

}

// 结果图:异常后面的语句不会打印

这里关于线程中的打断标识变量(之后以interrupt称)需要说明的是,在特定的情况下其状态会被重置。

1、线程内部在catch了异常了之后interrupt的状态会被重置为false。

2、线程调用了Thread.interrupted()方法之后,interrupt的状态会被重置为false。如果需要判断线程是否中断的话可以使用对象方法isInterrupted(),此方法不会重置。

所以在刚才的代码中需要加入return来结束线程,否则的话线程还是会继续往下执行,如下图

使用isInterrupted()实现:

public static void main(String[] args) throws InterruptedException {

Thread thread = new Thread(() -> {

while (!Thread.currentThread().isInterrupted()) {

int k = 0;

while (k++ < 10) {

System.out.println("do something..." + k);

}

}

System.err.println("thread end...");

});

thread.start();

Thread.sleep(1);

// 主线程流程执行完了,需要停止线程

thread.interrupt();

}

使用标识位来实现:定义一个变量标识线程是否终止,若终止了则退出run方法。跟上面isInterrupted()的实现一样,不过换成了volatile变量而已。

public class Test {

public static volatile boolean interrupted = false;

public static void main(String[] args) throws InterruptedException {

Thread thread = new Thread(() -> {

while (!interrupted) {

int k = 0;

while (k++ < 10) {

if (interrupted) {

System.err.println("thread invoke end....");

return;

}

System.out.println("do something..." + k);

}

}

System.err.println("thread end...");

});

thread.start();

Thread.sleep(1);

// 主线程流程执行完了,需要停止线程

interrupted = true;

}

}

// 结果图

stop()方法——不正确的线程中断方法

在线程提供的方法中还有一个方法可以强制关闭线程——stop()。这个方法可以说是相当的霸道,给人一种“我不管,我就是要你现在立刻死亡(指线程)”的感觉,并且其还会释放线程所有的锁资源,这样可能会导致出现数据不一致从而出现线程不安全的情况,如下面例子。

public class Test {

public static volatile boolean flag = false;

public int state = 0;

public static void main(String[] args) throws InterruptedException {

Test test = new Test();

Thread thread = new Thread(() -> {

synchronized (test) {

try {

test.state = 1;

Thread.sleep(100);

if (flag) {

test.state = 2;

}

System.err.println("thread execute finished...");

} catch (InterruptedException e) {

e.printStackTrace();

}

}

});

thread.start();

Thread.sleep(1);

thread.stop();

flag = true;

System.out.println("state状态:" + test.state);

}

}

// 在这段代码中,进入线程时默认将state赋为1,接着过一段时间后如果触发了特定条件则把state赋为2,但是在特定条件触发之前,线程就被终止掉了,这个特定条件虽然符合但却没办法执行,从而导致数据的不一致。

// 结果图

所以,我们应该采用上面两种正确的方式而不是stop()来中止线程。此外,stop()方法若在线程start()之前执行,那么在线程启动的时候就会立即死亡。

若有不对之处,望各位不吝指教(反正免费,对吧)。

总结

以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,谢谢大家对脚本之家的支持。

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

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

相关文章

win10控制面板快捷键_你没玩过的全新版本Win10,这些操作你知多少?

不知不觉&#xff0c;Windows 10与我们相伴已经整整四个年头了&#xff0c;从最开始的组团抗拒到现在的默默接受&#xff0c;个中滋味相信谁心里都有个数。近日微软开始推送“Win10更新五月版”&#xff0c;那么Win10中到底都有哪些“骚”操作&#xff1f;一起来看看吧。1、夜间…

1.编写登录接口

需求&#xff1a;.编写登录接口输入用户名密码认证成功后显示欢迎信息输错三次后锁定 # Author rendeleiwhile True: list1 [] list2 [] count int(3) f open("login.txt"&#xff0c;‘w’) for line in f: hostname str(line.split(\t)…

Linux redis故障,linux – Redis Stall故障排除

我们在服务器上运行了几个redis实例.还有多个Web层服务器连接到那些同时遇到停顿的实例.我们当时正在进行数据包捕获,确定在TX和RX流量中存在停顿,如下面的wireshark IO图&#xff1a;redis调用有一个相关的峰值,但我怀疑这是一个影响,而不是由于时滞造成的原因&#xff1a;使用…

吴恩达邀请9位AI大牛畅想2020:李开复看好医疗教育,LeCun强调自监督学习

来源&#xff1a;凹非寺2020&#xff0c;AI的研究会有哪些突破&#xff1f;2020&#xff0c;AI的应用又会有什么变化&#xff1f;吴恩达DeepLearning.ai旗下的THE BATCH刊物&#xff0c;分享了包括Yann LeCun、李开复、周志华、还有他们的老板吴恩达在内的10位AI大佬的新年寄语…

ivx中字体显示_iVX云服务费用优化 · 上篇

本文全文字数&#xff1a; 3308预计阅读时间&#xff1a; 10 分钟本文篇幅较长&#xff0c;建议亲亲能够完成阅读&#xff0c;将会学到不少干货哦~❤️本文目录一虚拟机->我们为何关闭了之前的虚拟机服务&#xff1f;->是否有新的虚拟机计划&#xff1f;二流量优化-&…

R pdf大小_限时免费获取 Mac上PDF压缩工具《Enolsoft PDF Compressor》

文章末尾有获取方式&#xff0c;按照以下步骤就能得到。我们不破解软件&#xff0c;所有优秀软件均来源于网络你的pdf文件太大使用不方便吗&#xff1f;赶紧来试试专业PDF压缩工具Enolsoft PDF Compressor破解版吧&#xff01;可以快速的压缩PDF文件的大小&#xff0c;支持批量…

未来十年有望改变世界的五大发现

来源&#xff1a;科技日报 浮云一别后&#xff0c;流水十年间&#xff01;21世纪第二个十年已悄然离开。过去十年&#xff0c;不少革命性突破和发现给人类生活和认知带来重大变革&#xff1a;希格斯玻色子填补了“标准模型”最后一块拼图&#xff0c;深化了人类对物质本质的理解…

fceux模拟器linux,FCEUX模拟器

FCEUX模拟器是一款游戏模拟器&#xff0c;可以用于FC/NES模拟器的游戏模拟&#xff0c;在模拟器中玩家可以游玩到那些经典的FC游戏&#xff0c;也就是我们所说的那些红白机游戏&#xff0c;比如经典的魂斗罗、超级马里奥等等&#xff0c;让你回到过去&#xff0c;回温这些经典的…

sql server select和set赋值的区别

--SQL Server中对已经定义的变量赋值的方式用两种&#xff0c;分别是 SET 和 SELECT --当表达式返回一个值并对一个变量进行赋值时&#xff0c;推荐使用 SET 方法 &#xff08;1&#xff09;SELECT可以在一条语句里对多个变量同时赋值,而SET只能一次对一个变量赋值 select p…

ddos应急处理_写给十九大安保应急的兄弟们 来看看DDOS攻击应急预案

阅读&#xff1a;4,205十一国庆以及紧接着的十九大即将到来&#xff0c;各位十九大安保应急的兄弟们都已经奔赴各自的一线&#xff0c;万事俱备只欠东风&#xff0c;大家的神经都紧绷着,紧急有序执行DDOS应急预案。“养兵千日用兵一时”&#xff0c;我们在平时把该做的准备都做…

el-table 树形表格 自定义展开图标_Image2icon for Mac(icon图标设计软件)

image2icon mac破解版是运行在Mac OS平台上的专业图标制作工具&#xff0c;用它可以创建你自己的Mac图标&#xff0c;并自定义文件和文件夹的icon图标。image2icon mac功能介绍轻松创建图标 厌倦了你的标准mac图标&#xff1f;您想个性化您的文件或文件夹吗&#xff1f;Image2i…

科技创新2030“新一代人工智能”重大项目2020年度第一批项目申报指南建议征求意见稿...

来源&#xff1a;锐动源编辑部设计&#xff1a;种 瑞审核&#xff1a;李建荣根据《国务院关于改进加强中央财政科研项目和资金管理的若干意见》&#xff08;国发〔2014〕11号&#xff09;、《国务院关于深化中央财政科技计划&#xff08;专项、基金等&#xff09;管理改革方案…

51单片机蜂鸣器演奏《小苹果》C语言程序,51单片机C语言蜂鸣器发声生日快乐播放程序...

《51单片机C语言蜂鸣器发声生日快乐播放程序》由会员分享&#xff0c;可在线阅读&#xff0c;更多相关《51单片机C语言蜂鸣器发声生日快乐播放程序(4页珍藏版)》请在人人文库网上搜索。1、按键发音/* 名称&#xff1a;按键发音说明&#xff1a;按下不同的按键会是SOUNDER发出不…

数据结构与算法系列——从菜鸟到入门

持续更新系列。 参考自&#xff1a;《数据结构与算法分析——Java语言描述》、《算法导论》 排序 数据结构——快速排序 数据结构——堆排序 数据结构——归并排序 数据结构——计数排序 数据结构——基数排序 队列和栈 链表 搜索 数据结构——二分搜索 二叉树 数据结构——二叉…

同时多个axios请求_用 React+Antd 封装 Axios 实现全局 Loading 效果

前言今天在做 react 后台管理的时候要实现一个全局 Loading 效果&#xff0c;通常使用 axios 库与后端进行数据交互。为了更好的用户体验&#xff0c;在每次请求前添加一个加载效果&#xff0c;让用户知道在等待加载。要实现这个功能&#xff0c;我们可以在每个组件请求手动添加…

jdk8 stream去重复_重复文件查找和清理工具

在Mac上怎样可以快速搜索和清理重复文件呢&#xff1f;小编建议您使用Tidy Up for Mac&#xff0c;是非常强大而使用简单的一款重复文件清理工具&#xff0c;Tidy Up 5带有简单的搜索模式&#xff0c;并且包括80多种预定义的智能搜索&#xff0c;可以快速而准确的帮助您查找重复…

c语言注释参与程序设计的编译,提高C语言程序设计教学的有益探索

摘要&#xff1a;在很多学校中&#xff0c;C语言的教学在学校的整个计算机编程语言的教学中占有很大比重&#xff0c;越来越多的学校认识到C语言的程序设计在整个编程中的所扮演的基础性的角色。关键词&#xff1a;C语言&#xff1b;教学&#xff1b;程序设计中图分类号&#x…

《科学》杂志展望2020年十大科学头条

来源&#xff1a;新华网 美国《科学》杂志2日刊文展望了2020年可能成为头条的十大科学新闻&#xff0c;中国建造全球首台E级超算、“基因剪刀”技术发布临床试验结果等入榜。这一权威学术刊物预测&#xff0c;中国有望在2020年建造出世界第一台E级超算。E级超算即百亿亿次超级计…

Android技巧分享——Android开发超好用工具吐血推荐 转载

内容中包含 base64string 图片造成字符过多&#xff0c;拒绝显示转载于:https://www.cnblogs.com/ydkf85/p/6562373.html

javaee实验报告心得_JavaEE实验报告.doc

JavaEE实验报告学 生 实 验 报 告(理工类)课程名称&#xff1a; J2EE程序设计 专业班级&#xff1a;学生学号&#xff1a; 学生姓名&#xff1a;所属院部&#xff1a; 信息技术学院 指导教师&#xff1a;20 13 ——20 14 学年 第 2 学期金陵科技学院教务处制实验报告书写要求实…