我们要知道Java中的线程状态转换,得先知道它有哪些状态,然后在研究它们在什么情况下才会转换。我们先看一下Java源码中是如何定义线程状态的,位置在
java.lang.Thread
类中的内部枚举类 public enum State
中,大概在1742行
/**
* A thread state. A thread can be in one of the following states:
* <ul>
* <li>{@link #NEW}<br>
* A thread that has not yet started is in this state.
* </li>
* <li>{@link #RUNNABLE}<br>
* A thread executing in the Java virtual machine is in this state.
* </li>
* <li>{@link #BLOCKED}<br>
* A thread that is blocked waiting for a monitor lock
* is in this state.
* </li>
* <li>{@link #WAITING}<br>
* A thread that is waiting indefinitely for another thread to
* perform a particular action is in this state.
* </li>
* <li>{@link #TIMED_WAITING}<br>
* A thread that is waiting for another thread to perform an action
* for up to a specified waiting time is in this state.
* </li>
* <li>{@link #TERMINATED}<br>
* A thread that has exited is in this state.
* </li>
* </ul>
*
* <p>
* A thread can be in only one state at a given point in time.
* These states are virtual machine states which do not reflect
* any operating system thread states.
*
* @since 1.5
* @see #getState
*/
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 <tt>Object.wait()</tt>
* on an object is waiting for another thread to call
* <tt>Object.notify()</tt> or <tt>Object.notifyAll()</tt> on
* that object. A thread that has called <tt>Thread.join()</tt>
* 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;
}
通过源码我们知道,Java是在1.5版本中才加入对线程支持的,也就是说一开始JDK其实是不支持多线程编程的。那源码中定义了6中状态分别是,
NEW: 新建
RUNNABLE: 就绪
BLOCK: 阻塞
WAITING: 等待
TIMED_WATING: 限时等待
TERMINATED: 终止
那为什么要区分这么多种状态呢? 注释都已经写得清清楚楚了。
NEW
/**
* Thread state for a thread which has not yet started.
*/
还没有开始的线程所处的状态
每一个线程,在堆内存中都有一个对应的Thread对象。Thread t = new Thread();当刚刚在堆内存中创建Thread对象,还没有调用t.start()方法之前,线程就处在NEW状态。在这个状态上,线程与普通的java对象没有什么区别,就仅仅是一个堆内存中的对象。
RUNNABLE
/**
* 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.
*/
线程在Java虚拟机中的状态,再该状态下,线程正在等待操作系统的处理器给他分配资源
对应 t.start() 调用的时候或者运行中的线程自己调用yield方法礼让一下的时候或者当前线程的cpu时间轮片到了出发了cpu中断,该线程响应中断后会改变状态,此时还会引起上下文的切换。
BLOCK
/**
* 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}.
*/
该状态下当前线程在等待一把锁。当遇到 synchronized 的时候就会处于该状态 或者调用一个对象的wait方法后被其他线程唤醒再次尝试获取 synchronized 锁的时候获取失败会再次进入该状态。
可见阻塞状态一定是跟锁有关的,也就是同步的时候,是因为线程获取不到锁才进入的状态,醒来的第一件事情一定是获取锁。获取到锁执行同步代码,获取不到锁就继续阻塞,直到下次醒来后继续执行。所以这个地方等待的是锁的释放。
WAITING,
- {@link Object#wait() Object.wait} with no timeout
当调用不加时间的wait方法的时候。注意这里要想调用wait方法一定得先获取到对象对应的锁。获取不到锁进入阻塞状态,获取到锁后才调用wait方法,这时候直接进入WAITING状态。这个地方等待的是有人来唤醒(调用notify或notifyAll) - {@link #join() Thread.join} with no timeout
把一个线程加到当前线程的执行流程中,也就是在join那个时间点等待执行线程的完成,完成后才继续执行,所以这是时候当前线程是处于WATING状态的,这个地方等待的是另一个线程执行完成后在唤醒。(其原理是先把当前线程挂起WATING,并把线程id传递给另一个线程,另一线程执行完成后,根据线程ID吧当前线程的状态改为RUNABLE。然后当前线程等待cpu调度)
Join 方法:本质上还是根据wait方法实现的。分析join源码发现join方法本身是使用了synchronized修饰符的。是加在方法上面的,意味着。 获取了当前对象的锁,然后继续发现里面的代码调用了wait。意味着我们先锁,再释放,等待唤醒,什么情况下被唤醒呢?执行结束的时候。调用wait之后一定阻塞的是当前线程,及时wait的对象是一个线程。 - {@link LockSupport#park() LockSupport.park}
可见等待状态其实与锁无关,它的唤醒一定是另一个线程完成某件事情后主动去唤醒(所谓唤醒,其实就是把状态改为RUNNABLE)
TIMED_WAITING
- {@link #sleep Thread.sleep}
- {@link Object#wait(long) Object.wait} with timeout
- {@link #join(long) Thread.join} with timeout
- {@link LockSupport#parkNanos LockSupport.parkNanos}
- {@link LockSupport#parkUntil LockSupport.parkUntil}
TIMED_WATTING 状态一定是和时间有关,等时间到了,自动出发唤醒(其实现原理是,先把线程ID 放到一个队列中,然后每隔时钟周期都检查是不是有线程到时间了,到了就把状态改为RUNABLE)。这个定时唤醒是系统时钟搞得鬼,系统时钟也是独立运行的时钟,可以像它上面注册时钟事件,当时间到了之后,就会发起中断,以唤醒进程。而且cpu一定会响应的。
TERMINATED
这个状态没有什么多说的,当线程运行结束的时候或者异常的时候就会别设置为该状态。已经是终态了。