源作者:人人都是程序员
idea如何在终端停止程序运行难度
初级
学习时间
20分钟
适合人群
零基础
开发语言
Java
开发环境
JDK v11
IntelliJ IDEA v2018.3
友情提示
本教学属于系列教学,内容具有连贯性,本章使用到的内容之前教学中都有详细讲解。
本章内容针对零基础或基础较差的同学比较友好,可能对于有基础的同学来说很简单,希望大家可以根据自己的实际情况选择继续看完或等待看下一篇文章。谢谢大家的谅解!
1.什么叫线程存活?
前面在《“全栈2019”Java多线程第五章:线程睡眠sleep()方法详解》
一章中讲了如何暂时停止执行线程。
在《“全栈2019”Java多线程第六章:中断线程interrupt()方法详解》
一章中又讲了如何停止线程。
在《“全栈2019”Java多线程第七章:等待线程死亡join()方法详解》
一章中讲了如何让一个线程等待另一个线程执行完毕再执行。
在《“全栈2019”Java多线程第八章:放弃执行权yield()方法详解》
一章中讲了如何让一个线程放弃执行权。
现在我们来讲解如何判断一个线程是否存活。
我们不禁要问:什么叫线程存活?
如果线程已经启动并且尚未死亡,则该线程处于存活状态。
下面我们来理解上述这段对线程存活的定义。
2.判断线程是否存活isAlive()方法
在Thread类中,我们可以通过isAlive()方法来判断线程是否存活。
isAlive()方法在Thread类中的源码:
将注释翻译成中文:
去掉注释版:
isAlive()方法的作用是判断线程是否存活。
访问权限
public:isAlive()方法访问权限是公开的。
final:isAlive()方法是最终的。不能被子类重写。
native:isAlive()方法具体是用本地方法实现的。
boolean:isAlive()方法返回boolean类型的值。线程存活返回true,否则返回false。
isAlive()方法只能被对象调用。
注:
native关键字:用来声明一个方法是由与计算机相关的语言(如C/C++/FORTRAN语言)实现的。
参数
无。
抛出的异常
无。
应用
我们先来创建一个线程:
然后调用它的isAlive()方法:
运行程序,执行结果:
从运行结果来看,好像有一点不对劲。
哪里不对劲?
我这个线程刚被创建出来,怎么就不是存活状态?
这里可能大家误会了,认为我们线程刚刚被创建出来应该是存活状态,其实它是线程尚未启动的线程状态。
“线程尚未启动的线程状态”什么意思?
通俗来说,线程被创建出来了,但是它还没有启动。
“启动”是什么?
启动就是调用线程的start()方法。
综上所述
线程被创建出来了,但是它还没有启动,它就是线程尚未启动的线程状态。
用线程状态类表示就是:Thread.State.NEW(下一章讲解线程状态)。
怎么让线程变为存活状态?
我们再来看一下线程存活状态定义:“如果线程已经启动并且尚未死亡,则该线程处于存活状态。”。
其中,“线程已经启动并且尚未死亡”非常重要。
启动:调用start()方法。
死亡:run()方法返回。
说明线程的存活状态在调用start()方法之后,到run()方法返回之前这段时间。
所以,我们需要调用start()方法再看看例子结果。
改写Main类:
运行程序,执行结果:
从运行结果来看,符合预期。
isAlive()方法返回true,说明我们线程是存活状态的。
刚刚说过,线程存活状态是在线程已经启动并且尚未死亡期间。如果我想看看线程死亡后,再调用isAlive()方法会不会返回false,怎么做呢?
我们可以使用while循环来判断看看:
此次改动有两处。
第一处,我们通过while循环判断线程是否存活,当线程一直处于存活状态时,执行while循环体:
第二处,当while循环条件为false时,也就是线程死亡时,程序继续往下执行:
运行程序,执行结果:
java如何停止一个正在运行的线程
从运行结果来看,线程执行完它的任务就死亡了。这一点也可以从结果中看不出:
线程任务:
线程执行完这行代码,run()方法就执行完毕了,即线程变成了死亡状态。
3.使用isAlive()方法改写数数例子
大家还记得我们在上一章《“全栈2019”Java多线程第八章:放弃执行权yield()方法详解》
中举的数数例子吗?不记得没关系,这里我们再来演示一下。
演示:
请使用两个线程分别完成各自的部分数数任务。
请观察程序代码及结果。
代码:
TaskAThread类:
TaskBThread类:
Main类:
结果:
动图太快?来个慢图(时长:19秒):
从运行结果来看,符合预期。
这里简单的来描述一下两个线程TaskAThread和TaskBThread它们各自的任务。
首先TaskAThread线程负责从0数到99:
TaskAThread数完之后,TaskBThread接着从100数到199:
因为线程都是同时运行的,所以我们上一章通过yield()方法的方式将TaskBThread任务B线程接在TaskAThread任务A线程后面运行。
具体做法是TaskAThread任务A线程在执行任务时,即使TaskBThread任务B线程拿到CPU执行权也要放弃,从而到达等TaskAThread任务A线程执行完任务之后TaskBThread任务B线程再接着执行:
这里while循环的判断条件是根据TaskAThread任务A线程里面的标记,这个标记是任务是否执行完毕:
今天,我们的任务就是干掉这个标记。
怎么干掉呢?
用isAlive()方法替代。
好,接下来,我们来演示一下新的程序代码。
演示:
请使用isAlive()方法替代TaskAThread类里面的任务是否完成标记。
请观察程序代码及结果。
代码:
TaskAThread类:
TaskBThread类:
Main类:
结果:
动图太快?来个慢图(时长:19秒):
从运行结果来看,符合预期。
此次程序一共改动过几处?
2处。
哪2处?
第一处,将TaskAThread类里面关于任务是否完成的标记全部删除:
第二处,将while循环的判断条件由之前的判断标记改为了判断线程是否存活(即isAlive()方法):
特别是这段代码,才是整个程序的灵魂。
taskAThread.isAlive()是判断任务A线程中的任务是否已经执行完毕。
while (taskAThread.isAlive())是当任务A线程还在执行任务时满足循环条件。
yield()是当任务A线程任务没有执行完毕时,任务B线程即使拿到执行权也要放弃此次执行机会。
总结
如果线程已经启动并且尚未死亡,则该线程处于存活状态。
isAlive()方法的作用是判断线程是否存活。
启动就是调用线程的start()方法。
死亡就是run方法执行完毕或返回。
线程被创建出来了,但是它还没有启动,它就是线程尚未启动的线程状态。
至此,Java中判断线程是否存活isAlive()方法相关内容讲解先告一段落,更多内容请持续关注。
答疑
如果大家有问题或想了解更多前沿技术,请在下方留言或评论,我会为大家解答。
上一章
“全栈2019”Java多线程第八章:放弃执行权yield()方法详解
下一章
“全栈2019”Java多线程第十章:Thread.State线程状态详解
学习小组
加入同步学习小组,共同交流与进步。
方式一:关注头条号Gorhaf,私信“Java学习小组”。
方式二:关注公众号Gorhaf,回复“Java学习小组”。
全栈工程师学习计划
关注我们,加入“全栈工程师学习计划”。
版权声明
原创不易,未经允许不得转载!