线程生命周期状态

在java中,任何对象都要有生命周期,线程也不例外,他也有自己的生命周期,当thread对象创建完成时,线程的生命周期便开始了,当run()方法中代码正常执行完成或者抛出一个未捕获的异常Exception或者是错误时,Error,线程生命周期便会结束,线程的整个生命周期可以分为6个阶段,传统线程模型中线程状态分为5个

  • 新建状态(New)
  • 就绪状态(Runnable)
  • 运行状态(Running)
  • 阻塞状态(Blocked)
  • 死亡状态(Terminated)

线程不同状态表明了线程当前正在进行的活动.在程序中通过一些操作可以使线程在不同状态之间转换

上图中展示了线程各种状态的转换关系,箭头表示可转换的方向,其中但箭头表示状态只能单向转换,列入线程只能从新建状态转换到就绪状态

java中有6种状态

传统线程模型(操作系统)中线程状态

新建状态New

创建一个线程对象后,该线程对象就处于新建状态,此时它不能运行,与其他的JAva对象一样,仅仅由java虚拟机为其分配了内存,没有表现出任何线程的动态特征

就绪状态Runnable

当线程对象调用了start方法后,该线程就进入就绪状态.处于就绪状态的线程位于线程队列中,此时它只是具备了运行的条件,能否获得CPU的使用权并开始运行,还需要等待系统的调度

运行状态Running

如果处于就绪状态的线程获取了cpu的使用权,并执行run()方法总的线程执行体,则该线程处于运行状态我.一个线程启动会,它可能不会一直处于运行状态,当运行状态的线程使用完系统分配的时间后,系统就会剥夺该线程占用的cpu资源让其他线程活得执行的机会,需要注意的是,只有处于就绪状态的线程才可能转换到运行状态

阻塞状态 Blocked

一个正在执行的线程在某些特殊情况下,如果被人为的挂起或执行耗时的输入/输出操作时,会让出CPU的使用权并暂时中止自己的执行,进入阻塞状态我.线程进入阻塞状态后,就不能进入排队队列.只有当引起阻塞的原因被消除后,线程才可以转入就绪状态

下面列举转换成阻塞状态的原因,以及如何从阻塞状态转换成就绪状态

  • 当线程属兔获取某个对象的同步锁时,如果该锁被其他线程持有,当前线程就会进入阻塞状态,如果想从阻塞状态进入就绪状态就必须获取到其他线程持有的锁
  • 当线程调用了一个阻塞式I/O方法时,该线程就会进入阻塞状态,如果想进入就绪状态就必须要等这个阻塞I/O方法返回
  • 当调用了某个对象的wait()方法时,也会使线程进入阻塞状态,如果想进入就绪状态就需要使用notify()方法唤醒该线程
  • 当调用了Thread的sleep(long millis)方法时,也会进入阻塞状态,在这种情况下,只需要到线程睡眠的时间了后,线程就会自动进入就绪状态
  • 当一个线程调用了另一个线程的join()方法时,会使当前线程进入阻塞状态,在这种情况下,需要等到新加入的线程运行结束后才会结束阻塞状态进入就绪状态

需要注意的是,线程从阻塞状态只能进入就绪状态,而不能直接进入运行状态,也就是说,结束阻塞的线程需要重新进入可运行池中,等待系统的调度

Sleep和wait的异同

  • wait和sleep方法都可以使线程进入阻塞状态
  • wait和sleep方法均是可中断方法,被中断后都会受到异常

不同

  • wait是Object方法,sleep是thread特有方法
  • wait方法执行必须在同步方法中进行,sleep不需要
  • 线程在同步方法执行sleep方法时,并不会释放monotor锁,而wait方法则会释放monitor锁,并且将线程添加到对象监视器中(monitor)的等待队列中
  • sleep方法短暂休眠之后会主动退出阻塞,而wait方法(没有指定wait时间)则需要被其他线程中断后才能退出阻塞。
  • sleep不需要被唤醒,但是wait是需要唤醒的

死亡状态 Dead

如果线程调用stop()方法或者run()方法正常执行完毕,或者线程抛出一个未捕获的异常或者错误,线程就进入死亡状态,一旦进入死亡状态,线程不再拥有 运行的资格,也不能转换到其他状态

java线程中的状态

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;
    }

我们可以看到实际上是分为6种状态的

初始状态(NEW)

线程被构建,但是还没有调用start方法

运行状态(RUNNABLE)

java把操作系统中就绪和运行俩种状态统一为运行中

阻塞状态(BLOCKED)

表示该线程进入等待状态,也就是线程因为某种原因放弃了CPU的使用权,阻塞也分为几种情况

  • 等待阻塞:运行的线程执行了Thread.sleep,wait,join等方法,JVM会把当前线程设置为等待状态,当sleep结束,join线程终止或者被唤醒后,该线程从等待状态进入阻塞状态,重新占用锁后进行线程恢复
  • 同步阻塞:运行的线程在获取对象的同步锁时,若改同步锁被其他线程锁占用了,那么当前JVM会把当前线程放到锁池中
  • 其他阻塞:发出I/O请求,JVM会把当前线程设置为阻塞状态,当I/O处理完毕则线程恢复

等待(WATING)

等待状态,没有超时时间(无线等待),要被其他线程或者有其他的中断操作

执行wait,join,lockSuport.park

超时等待(TIME_WAITING)

与等待不同的是,不是无限等待,超时等待是超时后自动返回

执行sleep,带参数的wait等待可以实现

终止(TEMINATED)

代表线程创建完毕

Last modification:December 12, 2022
如果觉得我的文章对你有用,请随意赞赏