线程的生命周期包括5个阶段:新建、就绪、运行、阻塞、销毁。
- 新建:刚使用new出来的线程对象
- 就绪:调用start( )方法后,这时线程处于等待CPU分配资源阶段(就是谁抢到CPU资源,谁就执行)
- 运行:当就绪状态的线程抢到CPU资源,就进入运行阶段,开始执行run()方法标志线程进入运行状态
- 阻塞:在运行时遇到阻塞事件(用户输入、sleep方法、wait方法等)此时线程就处于阻塞状态,阻塞状态会让出CPU并临时中止自己的执行
- 销毁:线程正常执行完run()方法 或者 线程被强行终止 亦或者 异常导致结束,线程就被销毁,释放资源。
完整的生命周期图:
在JDK中用Thread.State类中定义了线程的几种状态:
public enum State {
// 新建
/**
* Thread state for a thread which has not yet started.
*/
NEW,
/**
* Thread state for a runnable thread. A thread in the runnable
* state is executing in the Java virtual machine but it may
* be waiting for other resources from the operating system
* such as processor.
*/
// 运行
RUNNABLE,
/**
* Thread state for a thread blocked waiting for a monitor lock.
* A thread in the blocked state is waiting for a monitor lock
* to enter a synchronized block/method or
* reenter a synchronized block/method after calling
* {@link Object#wait() Object.wait}.
*/
//阻塞
BLOCKED,
/**
* Thread state for a waiting thread.
* A thread is in the waiting state due to calling one of the
* following methods:
* <ul>
* <li>{@link Object#wait() Object.wait} with no timeout</li>
* <li>{@link #join() Thread.join} with no timeout</li>
* <li>{@link LockSupport#park() LockSupport.park}</li>
* </ul>
*
* <p>A thread in the waiting state is waiting for another thread to
* perform a particular action.
*
* For example, a thread that has called {@code Object.wait()}
* on an object is waiting for another thread to call
* {@code Object.notify()} or {@code Object.notifyAll()} on
* that object. A thread that has called {@code Thread.join()}
* is waiting for a specified thread to terminate.
*/
//等待 一直等待
WAITING,
/**
* Thread state for a waiting thread with a specified waiting time.
* A thread is in the timed waiting state due to calling one of
* the following methods with a specified positive waiting time:
* <ul>
* <li>{@link #sleep Thread.sleep}</li>
* <li>{@link Object#wait(long) Object.wait} with timeout</li>
* <li>{@link #join(long) Thread.join} with timeout</li>
* <li>{@link LockSupport#parkNanos LockSupport.parkNanos}</li>
* <li>{@link LockSupport#parkUntil LockSupport.parkUntil}</li>
* </ul>
*/
// 超时等待
TIMED_WAITING,
/**
* Thread state for a terminated thread.
* The thread has completed execution.
*/
//终止 死亡
TERMINATED;
}
现在介绍一下各个状态
1、新建状态
看看下面一行代码:
Thread2 r= new Thread2();
在Java语言中是线程被创建了(但是从操作系统看,真正的线程还没被创建,调用完start()方法才会被创建)
2、就绪状态
进入就绪状态代码:
t1.start();
就绪状态的线程又被叫做可运行状态,表示当前的线程具备抢占CPU时间片(执行权)的资格,当抢到CPU时间片(执行权)就会执行run方法,这时线程进入运行状态。
在这里需要知道 start()方法的作用是:启动一个分支线程,在JVM中开辟一个新的栈空间,这段代码就瞬间结束。一个线程就是一个栈,栈的内存是独立的,不共享的。
有必要大致了解调用start()方法的JVM:
3、运行状态
当某个线程抢到CPU时间片(执行权),该线程就会进入运行状态(Running),开始调用run()方法中的逻辑代码。
在这个状态可以转变为哪几个状态呢?看下吗的图就可清楚知道:
- ①线:当该线程时间片用完 等待抢下次CUP资源 或者 线程主动调用yield方法,让出CPU资源;或者 正在等待集合中,被其他线程调用notify / notifyAll方法唤醒,进入就绪状态。
普及一下时间片用完:CPU把所有的时间分成相等的很小的时间片,每个进程只能得到一个时间片去执行,在这个时间片完成任务是最好的,没完成就到先暂停等待抢占下次的执行时间片来完成。
- ②线:调用了sleep方法(等待sleep时间过,线程重新进入可执行状态(就绪状态),再次抢到CPU执行权就继续执行下面任务,会保存上次执行的记录,继续往后执行),wait方法被加入到等待集合中,控制台输入事件、进行IO阻塞操作.....
- ③线:调用stop方法 或者 run方法正常执行完。
4、阻塞状态
当一个线程遇到一些阻塞事件就会被阻塞,比如sleep方法、用户键盘输入事件;这时该线程就会放弃CPU执行时间片。
阻塞时的状态可以转为哪些状态:就绪状态、结束/死亡,如下图:
- ①线:sleep()时间到 或者 获得同步锁、notify()、notifyAll()....
- ②线:调用stop方法或者出现异常错误。
5、终止状态(死亡)
进入该状态意味着线程的生命终结,该过程不可以再转为其他状态。线程进入终止状态有一下情况:
- 线程正常运行结束,run方法运行完。
- 线程出现意外错位终止,JVM异常结束。