介绍
这篇文章将为大家详细讲解有关Java中启动线程的正确和错误方式是什么,小编觉得挺实用的,因此分享给大家做个参考,希望大家阅读完这篇文章后可以有所收获。
细品Java中启动线程的正确和错误方式
开始方法和运行方法的比较
<强>代码演示:强>
/* * * & lt; p> *开始()和()的运行比较 * & lt;/p> * * @author踏雪彡寻梅 * @version 1.0 * @date 2020/9/20 - 16:15 * @since JDK1.8 */公共类StartAndRunMethod{公共静态void main (String [] args){//运行方法演示//输出:名字:主要//说明由主线程去执行的,不符合新建一个线程的本意 可运行Runnable=()→{ System.out.println(名字:“;+ Thread.currentThread () . getname ()); }; runnable.run ();//开始方法演示//输出:名字:Thread-0//说明新建了一个线程,符合本意 新线程(runnable) .start (); } }复制代码
从以上示例可以分析出以下两点:
- <李>
直接使用<代码> 代码>运行方法不会启动一个新线程。(错误方式)
李> <李><代码> 代码>开始方法会启动一个新线程。(正确方式)
李>开始方法分析
开始方法的含义以及注意事项
- <李>
<代码> 代码>开始方法可以启动一个新线程。
- <李>线程对象在初始化之后调用了<代码> 代码>开始方法之后,当前线程(通常是主线程)会请求JVM虚拟机如果有空闲的话来启动一下这边的这个新线程。李> <李>也就是说,启动一个新线程的本质就是请求JVM来运行这个线程。李> <李>至于这个线程何时能够运行,并不是简单的由我们能够决定的,而是由线程调度器去决定的。李> <李>如果它很忙,即使我们运行了<代码> 代码>开始方法,也不一定能够立刻的启动线程。李> <李>所以说<代码> srtart 代码>方法调用之后,并不意味这个方法已经开始运行了。它可能稍后才会运行,也很有可能很长时间都不会运行,比如说遇到了饥饿的情况。李> <李>这也就印证了有些情况下,线程1先掉用了<代码> 代码>开始方法,而线程2后调用了<代码> 代码>开始方法,却发现线程2先执行线程1后执行的情况。李> <李>总结:调用<代码> 代码>开始方法的顺序并不能决定真正线程执行的顺序。李> <李> <强>注意事项强>
- <李> <代码> 代码>开始方法会牵扯到两个线程。李> <李>第一个就是主线程,因为我们必须要有一个主线程或者是其他的线程(哪怕不是主线程)来执行这个<代码> 代码>开始方法,第二个才是新的线程。李> <李>很多情况下会忽略掉为我们创建线程的这个主线程,不要误以为调用了<代码> 代码>开始就已经是子线程去执行了,这个语句其实是主线程或者说是父线程来执行的,被执行之后才去创建新线程。李>
<代码> 代码>开始方法创建新线程的准备工作
- <李>首先,它会让自己处于就绪状态。
- <李>就绪状态指已经获取到除了CPU以外的其他资源,如已经设置了上下文,栈,线程状态以及电脑(PC是一个寄存器,电脑指向程序运行的位置)等。李>
<强>需要注意:不能重复的执行开始方法强>
- <李>
代码示例
/* * * & lt; p> *演示不能重复的执行开始方法(两次及以上),否则会报的错 * & lt;/p> * * @author踏雪彡寻梅 * @version 1.0 * @date 2020/9/20——16:47 * @since JDK1.8 */公共类CantStartTwice{公共静态void main (String [] args) { 可运行Runnable=()→{ System.out.println(名字:“;+ Thread.currentThread () . getname ()); }; 线程的线程=新线程(可运行);//输出:名字:Thread-0 thread.start ();//输出:抛出java.lang.IllegalThreadStateException//即非法线程状态异常(线程状态不符合规定) thread.start (); } }复制代码李> <李>
报错的原因
- <李> <代码> 代码>开始一旦开始执行,线程状态就从最开始的新状态进入到后续的状态,比如说Runnable,然后一旦线程执行完毕,线程就会变成终止状态,而终止状态永远不可能再返回回去,所以会抛出以上异常,也就是说不能回到初始状态了。这里描述的还不够清晰,让我们来看看源码能了解的更透彻。