Java线程状态介绍与示例——线程的生命周期
已发表: 2019-01-11
线程状态
下图说明了 Java 线程在其生命周期中的任何时候可能处于的各种状态,以及哪些方法调用会导致转换到另一个状态。 该图不是一个完整的有限状态图,而是一个线程生命中更有趣和更常见的方面的概述。
如果您有以下任何问题,那么您来对地方了:
- Java中线程的生命周期
- Java中线程的生命周期和状态
- 了解 Java 线程状态
本页的其余部分根据其状态讨论Thread's life cycle
。

新线程
下面的语句创建了一个新线程,但没有启动它,从而使线程处于图中标记为 New Thread 的状态。
1 |
Thread myThread = new MyThreadClass ( ) ; |
当一个线程处于New Thread
状态时,它只是一个空的 Thread 对象。 尚未为其分配系统资源。 因此当线程处于这种状态时,只能启动或停止线程; 当线程处于此状态时调用除start()
或stop()
之外的任何其他方法都没有意义,并导致 IllegalThreadStateException。
可运行
现在考虑这两行代码:
1 2 |
Thread myThread = new MyThreadClass ( ) ; myThread . start ( ) ; |
start()
方法创建运行线程所需的系统资源,调度线程运行,并调用线程的run()
方法。 此时线程处于“可运行”状态。 这种状态称为“Runnable”而不是“Running”,因为线程在这种状态下可能实际上并未运行。 许多计算机只有一个处理器,因此不可能同时运行所有“可运行”线程。
因此,Java 运行时系统必须实现一个调度方案,在所有“可运行”线程之间共享处理器。 但是,对于大多数目的,您可以将“可运行”状态简单地视为“正在运行”。 当一个线程正在运行时——它是“可运行的”并且是当前线程——它的run()
中的指令是按顺序执行的。
不可运行
当以下四个事件之一发生时,线程进入Not Runnable
状态:
- 有人调用它的
suspend()
方法 - 有人调用它的
sleep()
方法 - 线程使用它的
wait()
方法等待条件变量 - 线程在 I/O 上阻塞。
例如,此代码段中的粗体行
1 2 3 4 5 6 |
Thread myThread = new MyThreadClass ( ) ; myThread . start ( ) ; try { myThread . sleep ( 10000 ) ; } catch ( InterruptedException e ) { } |
使myThread
休眠 10 秒(10,000 毫秒)。 在这 10 秒内,即使处理器可用, myThread
也不会运行。 10 秒后, myThread
再次变为“可运行”,现在如果处理器可用, myThread
将运行。
对于上面列出的进入“不可运行”状态的每个“入口”,都有一个特定且不同的逃生路线将线程返回到“可运行”状态。 逃生路线仅适用于其相应的“入口”。 例如,如果一个线程已经进入睡眠状态,那么在线程再次变为“可运行”之前必须经过指定的毫秒数。 在休眠线程上调用resume()
无效。
以下指示了进入“不可运行”状态的每个入口的逃生路线。
- 如果线程已进入睡眠状态,则必须经过指定的毫秒数。
- 如果一个线程被挂起,那么必须有人调用它的
resume()
方法。 - 如果线程正在等待条件变量,则拥有该变量的任何对象都必须通过调用
notify()
或notifyAll()
放弃它。 - 如果线程在 I/O 上被阻塞,则指定的 I/O 命令必须完成。

死的
线程可能以两种方式死亡:自然原因或被杀死(停止)。 当其run()
方法正常退出时,线程自然死亡。 例如,该方法中的while
循环是一个有限循环——它将迭代 100 次然后退出。

1 2 3 4 5 6 7 |
public void run ( ) { int i = 0 ; while ( i < 100 ) { i ++ ; System . out . println ( "i = " + i ) ; } } |
在循环和run()
方法完成后,具有此run()
方法的线程将自然死亡。
你也可以随时通过调用它的stop()
方法来终止一个线程。 此代码片段。
1 2 3 4 5 6 7 |
Thread myThread = new MyThreadClass ( ) ; myThread . start ( ) ; try { Thread . currentThread ( ) . sleep ( 10000 ) ; } catch ( InterruptedException e ) { } myThread . stop ( ) ; |
创建并启动myThread
然后让当前线程休眠 10 秒。 当当前线程唤醒时,代码段中的粗线将杀死myThread
。
stop()
方法在线程上抛出一个 ThreadDeath 对象来杀死它。 因此,当一个线程以这种方式被杀死时,它会异步死亡。 线程在实际接收到 ThreadDeath 异常时将死亡。
非法线程状态异常
当您调用线程上的方法并且该线程的状态不允许该方法调用时,运行时系统会引发 IllegalThreadStateException。 例如,当您在不是“可运行”的线程上调用suspend()
时,会引发 IllegalThreadStateException。
如本课到目前为止的各种线程示例所示,当您调用一个可以抛出异常的线程方法时,您必须要么捕获并处理异常,要么声明调用方法抛出未捕获的异常。
isAlive() 方法
关于线程状态的最后一句话:Thread 类的编程接口包括一个名为isAlive()
的方法。 如果线程已启动且未停止,则isAlive()
返回 true。 因此,如果isAlive()
方法返回false ,您就知道该线程是“新线程”或“死线程”。
如果isAlive()
方法返回true ,你就知道线程要么是“Runnable”,要么是“Not Runnable”。 您无法区分“新线程”和“死线程”; 您也无法区分“可运行”线程和“不可运行”线程。
在查看复杂的线程示例时,在网上发现了这个非常棒的教程。 每个人都应该仔细阅读这篇文章。