16.3.1 新建状态和就绪状态
什么时候线程处于新建状态
当程序使用new
关键字创建了一个线程之后,该线程就处于新建状态
,此时它和其他的Java
对象样,仅仅由Java
虚拟机为其分配内存,并初始化其成员变量的值。此时的线程对象没有表现出任何线程的动态特征,程序也不会执行线程的线程执行体。
什么时候线程处于就绪状态
当线程对象调用了start
方法之后,该线程处于就绪状态
,Java
虚拟机会为其创建方法调用栈和程序计数器,处于这个状态中的线程并没有开始运行,只是表示该线程可以运行了。至于该线程何时开始运行,取决于JVM
里线程调度器的调度。
永远不要调用线程对象的run方法
启动线程使用start()
方法,而不是run()
方法!永远不要调用线程对象的run()
方法!
- 调用
start()
方法来启动线程,系统会把该run()
方法当成线程执行体来处理; - 如果直接调用线程对象的
run()
方法,系统把线程对象当成一个普通对象,把run()
方法当成一个普通方法,而不是线程执行体,run()
方法将立即就会被执行,而且在run()
方法返回之前其他线程无法并发执行
程序示例
1 | public class InvokeRun extends Thread |
运行效果:
1 | main 0 |
上面程序创建线程对象后直接调用了线程对象的run()
方法,程序运行的结果是整个程序只有一个线程:主线程
。还有一点需要指出,如果直接调用线程对象的run()
方法,则run()
方法里不能直接通过getName()
方法来获得当前执行线程的名字,而是需要使用Thread.currentThread()
方法先获得当前线程,再调用线程对象的getName()
方法来获得线程的名字。
通过上面程序不难看出,启动线程的正确方法是调用Thread
对象的start()
方法,而不是直接调用run()
方法,否则就变成单线程程序了
只能对处于新建状态的线程调用start方法
只能对处于新建状态的线程调用start
方法,否则将引发IllegalThreadStateException
异常。调用了线程的run()
方法之后,该线程已经不再处于新建状态,不要再次调用线程对象的start()
方法。
调用线程对象的start
方法之后,该线程立即进入就绪状态——就绪状态相当于”等待执行”,但该线程并未真正进入运行状态。
如何让子线程立即执行
如果希望调用子线程的start
方法后子线程立即开始执行,程序可以使用Thread.sleep(1)
来让当前运行的线程(主线程)睡眠1毫秒
——1毫秒就够了,因为在这1毫秒内CPU
不会空闲,它会去执行另一个处于就绪状态的线程,这样就可以让子线程立即开始执行。
本文重点
- 当程序使用
new
关键字创建了一个线程之后,该线程就处于新建状态
- 当线程对象调用了
start
方法之后,该线程处于就绪状态
,就绪状态相当于”等待执行”状态,此时该线程并未真正进入运行状态。 - 只能对处于新建状态的线程调用
start
方法,否则将引发IllegalThreadStateException
异常 - 启动线程的正确方法是调用
Thread
对象的start()
方法,而不是直接调用run()
方法,直接调用了线程对象的run()
方法,程序运行的结果是整个程序只有一个线程:主线程
- 如果希望调用子线程的
start
方法后子线程立即开始执行,则可以让当前运行的线程(主线程)睡眠1毫秒
,这种情况针只有一个子线程的情况,个人觉得用处不大.原文链接: 16.3.1 新建状态和就绪状态