天天看点

多线程-线程的状态(生命周期)详解

一:线程到底有多少种状态?

在网上看了不少博客,说线程有5中状态,也有的说线程有6中状态,比较纠结,就看了一下源码;Thread类中有枚举类State说的很清楚,有六种状态:NEW,RUNNABLE,BLOCKED, WAITING,TIMED_WAITING,TERMINATED;

public enum State {
        NEW,
        RUNNABLE,
        BLOCKED,
        WAITING,
        TIMED_WAITING,
        TERMINATED;
    }
           

二:线程间状态的切换

多线程-线程的状态(生命周期)详解

NEW状态:

java.lang.Thread.State枚举的描述:

/**
 * Thread state for a thread which has not yet started.
  */
 NEW,
           

当我们使用关键字new创建一个新的Thread对象时,它并不处于执行状态,因为没有调用start方法启动该线程,该线程此时的状态就是NEW状态;也就是说他只是Thread对象的状态,因为在没有调用start方法之前,该线程基本不存在,他就是我们平时用new关键字创建的对象没有区别;NEW状态通过调用start方法进入RUNNABLE状态

RUNNABLE状态:

java.lang.Thread.State枚举的描述:

/**
  * 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,
           

线程对象创建后,调用start方法,此时才是真正的在JVM进程中创建一个线程;但是此时并不是已经立即得到了执行;线程的运行与否都要通过CPU的调度,这个中间状态称为可执行状态(RUNNABLE),此时也就是说该线程有执行的资格,但是没有真正的执行起来而是等待CPU的调度;这种状态下,即使在线程的执行逻辑中调用wait,sleep或者其他block的IO操作等,也必须获得CPU的调度执行权才可以,严格的意义上讲RUNNABLE状态的线程只能意外终止或者进入RUNNING状态。

BLOCKED状态:

/**
   * 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,
           

BLOCKED称为阻塞状态,或者说线程已经被挂起,原因通常是它在等待一个“锁”,当尝试进入一个synchronized语句块/方法时,锁已经被其它线程占有,就会被阻塞,直到另一个线程走完临界区或发生了相应锁对象的wait()操作后,它才有机会去争夺进入临界区的权利;

该状态可以切换到下面几个状态:

1:直接进入TERMINATED状态,比如调用JDK已经不推荐的STOP方法或者意外死亡

2:线程阻塞的操作结束进入到RUNNABLE状态

3:线程完成了指定的休眠,进入到了RUNNABLE状态

4:WAIT中的线程比其他线程notify()/notifyAll()唤醒,进入RUNNABLE状态

5:线程获取到了某个锁资源,进入RUNNABLE状态

6:线程的阻塞状态被打断,比如调用了interrupt方法,进入RUNNABLE方法

WAITING状态(等待状态):

/**
  * 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,
           

处于这种状态的线程不会被分配CPU执行时间,它们要等待显示的被其它线程唤醒。这种状态通常是指一个线程拥有对象锁后进入到相应的代码区域后,调用相应的“锁对象”的wait()方法操作后产生的一种结果。变相的实现还有LockSupport.park()、Thread.join()等,它们也是在等待另一个事件的发生,也就是描述了等待的意思。

调用以下方法会让线程陷入无限期等待状态:

(1)没有设置timeout参数的Object.wait()

(2)没有设置timeout参数的Thread.join()

(3)LockSupport.park()

TIMED_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,
           

处于这种状态的线程也不会被分配CPU执行时间,不过无需等待被其它线程显示的唤醒,在一定时间之后它们会由系统自动的唤醒。

以下方法会让线程进入TIMED_WAITING限期等待状态:

(1)Thread.sleep()方法

(2)设置了timeout参数的Object.wait()方法

(3)设置了timeout参数的Thread.join()方法

(4)LockSupport.parkNanos()方法

(5)LockSupport.parkUntil()方法

TERMINATED状态

/**
  * Thread state for a terminated thread.
   * The thread has completed execution.
   */
  TERMINATED;
           

TERMINATED状态是一个线程的最终状态,在该状态中线程不会切换到其他任何状态,线程进入TERMINATED的状态,就说明该线程的整个生命周期就结束了;

以下这些情况会让线程终止:

1:线程正常运行结束,结束生命周期

2:线程运行出错意外终止

3:JVM Crash导致所有的线程都结束

注:我们从源码中可以看出:其实时没有运行中RUNNING这个状态的,

这个RUNNING其实就是线程调度程序从可运行池中选择一个线程作为当前线程时线程所处的状态;也就是CPU通过轮询或者其他方式从任务可执行队列中选中了线程

继续阅读