java线程和操作(Java多线程第十二章)
java线程和操作(Java多线程第十二章)在《“全栈2019”Java多线程第九章:判断线程是否存活isAlive()详解》一章中讲了如何判断一个线程是否存活。在《“全栈2019”Java多线程第八章:放弃执行权yield()方法详解》一章中讲了如何让一个线程放弃执行权。前面在《“全栈2019”Java多线程第五章:线程睡眠sleep()方法详解》一章中讲了如何暂时停止执行线程。在《“全栈2019”Java多线程第六章:中断线程interrupt()方法详解》一章中又讲了如何停止线程。在《“全栈2019”Java多线程第七章:等待线程死亡join()方法详解》一章中讲了如何让一个线程等待另一个线程执行完毕再执行。
难度初级
学习时间10分钟
适合人群零基础
开发语言java
开发环境- JDK v11
- IntelliJ IDEA v2018.3
- 本教学属于系列教学,内容具有连贯性,本章使用到的内容之前教学中都有详细讲解。
- 本章内容针对零基础或基础较差的同学比较友好,可能对于有基础的同学来说很简单,希望大家可以根据自己的实际情况选择继续看完或等待看下一篇文章。谢谢大家的谅解!
前面在《“全栈2019”Java多线程第五章:线程睡眠sleep()方法详解》一章中讲了如何暂时停止执行线程。
在《“全栈2019”Java多线程第六章:中断线程interrupt()方法详解》一章中又讲了如何停止线程。
在《“全栈2019”Java多线程第七章:等待线程死亡join()方法详解》一章中讲了如何让一个线程等待另一个线程执行完毕再执行。
在《“全栈2019”Java多线程第八章:放弃执行权yield()方法详解》一章中讲了如何让一个线程放弃执行权。
在《“全栈2019”Java多线程第九章:判断线程是否存活isAlive()详解》一章中讲了如何判断一个线程是否存活。
在《“全栈2019”Java多线程第十章:Thread.State线程状态详解》一章中讲了线程的6种状态。
在《“全栈2019”Java多线程第十一章:线程优先级详解》一章中讲了如何设置/获取线程的优先级。
结果:
从运行结果来看,程序没有问题。
我们当前线程的名称为main,即主线程。
进程就是一个独立运行的程序,简单来说就是进程是一个应用程序:
上述代码就是一个Java应用程序,它也是一个进程。
每个进程中至少有一个线程。在我们这个应用程序中,对应的就是主线程:
线程是进程的最基本执行单元。即主线程在执行我们的代码:
现在将三句话都有Java应用程序相对应,下面我们就来说说什么是前台线程。
3.什么是前台线程?线程必须运行完进程才可以退出,这类线程被称之为前台线程。
上面这句话什么意思?
我们来分词解释 举例说明。
第一句,线程必须运行完进程才可以退出:
这里进程我们就拿Java应用程序来说明:
请问:上述Java应用程序什么情况下会退出?
在执行完main()方法就会退出。
再请问:main()方法执行靠的什么?
靠的是主线程。
所以,上述Java应用程序在执行完主线程之后就会退出。
即,进程在执行完主线程之后就会退出。
同时也说明了主线程就是前台线程。
第二句,这类线程被称之为前台线程:
“这类线程被称之为前台线程”中的“这类”一词说明前台线程不止主线程一个。那么,我们平时创建的线程是不是前台线程呢?来看看。
运行程序,执行结果:
从运行结果来看,我们的程序是在main线程和新创建的线程执行完毕后才退出的。
所以,主线程和新创建的线程默认都是前台线程。
4.应用程序必须运行完所有的前台线程才可以退出其实上一小节已经说明了这个问题,我们这里再多创建几个线程加以证明。
运行程序,执行结果:
从运行结果来看,符合预期。
我们的Java应用程序的确是在所有前台线程运行完毕之后才退出的。
说完前台线程,再来说说后台线程。
5.什么是后台线程?不必考虑线程是否运行完进程就可以退出,这类线程被称之为后台线程。
大家,我们在解释上述描述之前,先来介绍一个方法,这个方法可以将线程设置为后台线程,这个方法叫做setDaemon(boolean on)。
setDaemon(boolean on)方法在Thread类中的源码:
将注释翻译成中文:
去掉注释版:
setDaemon(boolean on)方法的作用就是将线程设置为后台线程。
访问权限public:setDaemon(boolean on)方法访问权限是公开的。
final:setDaemon(boolean on)方法是最终的。不能被子类重写。
void:setDaemon(boolean on)方法无返回值。
setDaemon(boolean on)方法只能被对象调用。
参数boolean on:boolean类型。是否将线程设置为后台线程。如果为true,则把线程设置后台线程。
抛出的异常throws IllegalThreadStateException:如果线程处于存活状态则抛出此异常。
throws SecurityException:当当前线程不能设置此线程时抛出此异常。
应用接下来,我们来演示一个前台线程和一个后台线程同时存在会是什么样。
演示:
请创建一个前台线程。
请创建一个后台线程。
请观察程序代码及结果。
代码:
Main类:
结果:
从运行结果来看,符合我们预期。
为什么说符合预期?
因为我们在描述什么是后台线程的时候说过“不必考虑线程是否运行完进程就可以退出,这类线程被称之为后台线程。”而进程是要等所有前台线程执行完才可以退出的,所以当所有前台线程执行完时,进程退出,后台线程也退出了。这个应用程序正好反映了这一点。
具体是什么反映的呢?
我们来看看程序代码。
首先,我们创建了两个线程,目前这两个线程都是前台线程,因为新创建的线程默认都是前台线程:
然后,我们将线程thread2设置为后台线程:
这里我们需要注意的是,前台线程thread1执行的任务是循环100遍:
后台线程thread2执行的任务是无限循环:
按照后台线程在所有前台线程执行完后也随进程一并退出原则,此程序中,当thread1线程执行循环100遍之后程序将结束,我们来看结果是否如此呢:
结果正是如此。
故,证实我们后台线程在所有前台线程执行完后也随进程一并退出。
现在我们再去看关于后台线程的描述:“不必考虑线程是否运行完进程就可以退出,这类线程被称之为后台线程。”就很好理解了。即进程必须运行完所有的前台线程才可以退出;而对于后台线程,进程则可以不考虑其是否已经运行完毕而直接退出,所有的后台线程在应用程序退出时都会自动结束。
6.已经存活的线程不能再设置为后台线程在《“全栈2019”Java多线程第九章:判断线程是否存活isAlive()详解》一章中讲了如何判断一个线程是否存活。这里就不再赘述什么是存活的线程了。
接下来,我们来演示下当把一个已存活的线程设置为后台线程时会怎样。
演示:
请把一个已存活的线程设置为后台线程。
请观察程序代码及结果。
代码:
Main类:
结果:
错误信息:
文字版:
Exception in thread "main"
java.lang.IllegalThreadStateException
at java.base/java.lang.Thread.setDaemon(Thread.java:1410)
at main.Main.main(Main.java:30)
从运行结果来看,我们程序发生了错误。
是什么原因导致的呢?
是我们在线程已经存活状态下还去设置它为后台线程导致的。
即,下面这行代码:
在这行代码未执行之前,我们的thread1线程和thread2线程都是前台线程,而且它们都启动起来了。
这里我们需要弄明白的是线程存活状态指的是哪个时间段?
线程存活状态指的是线程调用start()方法之后到run()方法执行完或返回这段时间。
也就是说,我们线程被启动起来以后就不能再被设置为后台线程了。
7.判断一个线程是否为后台线程isDaemon()方法前面说了那么多如何将一个线程设置为后台线程,那么我们如何判断一个线程是否为后台线程呢?
我们可以通过线程的isDaemon()方法来判断线程是否为后台线程。
isDaemon()方法在Thread类中的源码:
将注释翻译成中文:
去掉注释版:
isDaemon()方法的作用是判断线程是否为后台线程。
访问权限public:isDaemon()方法访问权限是公开的。
final:isDaemon()方法是最终的。不能被子类重写。
boolean:isDaemon()方法返回boolean值。当线程为后台线程时,返回true,否则返回false。
isDaemon()方法只能被对象调用。
参数无。
抛出的异常无。
应用接下来,我们来创建两个线程,然后将其中一个线程设置为后台线程,再来调用它们的isDaemon()方法判断它们是否为后台线程。
演示:
请创建两个线程,一个为前台线程,一个为后台线程。
请观察程序代码及结果。
代码:
Main类:
结果:
从运行结果来看,符合预期。
回顾程序代码,首先,我们创建了两个线程,目前它们默认都是前台线程:
然后,我们将thread2线程设置为后台线程:
接着,我们调用它们的isDaemon()方法来判断它们是否为后台线程:
然后,我们启动它们:
执行结果:
从结果中,我们可以看到thread2线程为后台线程。
8.后台线程使用技巧我们的前台线程应该去做一些执行时间较长的任务,如后面要学的Web服务,处理用户请求。
而后台线程应该去做一些执行时间较短的任务,如处理Web服务中的某一项操作,像检查系统资源一类的检查性工作。
总结- 线程必须运行完进程才可以退出,这类线程被称之为前台线程。
- 主线程和新创建的线程默认都是前台线程。
- 不必考虑线程是否运行完进程就可以退出,这类线程被称之为后台线程。
- setDaemon(boolean on)方法的作用就是将线程设置为后台线程。
- 进程必须运行完所有的前台线程才可以退出;而对于后台线程,进程则可以不考虑其是否已经运行完毕而直接退出,所有的后台线程在应用程序退出时都会自动结束。
- 已经存活的线程不能再设置为后台线程。
- isDaemon()方法的作用是判断线程是否为后台线程。
- 前台线程应该去做一些执行时间较长的任务,如后面要学的Web服务,处理用户请求。
- 后台线程应该去做一些执行时间较短的任务,如处理Web服务中的某一项操作,像检查系统资源一类的检查性工作。
至此,Java中后台线程相关内容讲解先告一段落,更多内容请持续关注。
答疑如果大家有问题或想了解更多前沿技术,请在下方留言或评论,我会为大家解答。
上一章“全栈2019”Java多线程第十一章:线程优先级详解
下一章“全栈2019”Java多线程第十三章:线程组ThreadGroup详解
学习小组加入同步学习小组,共同交流与进步。
- 方式一:关注头条号Gorhaf,私信“Java学习小组”。
- 方式二:关注公众号Gorhaf,回复“Java学习小组”。
关注我们,加入“全栈工程师学习计划”。
原创不易,未经允许不得转载!