Java-多线程-线程状态

Java-多线程-线程状态

1 简介

Java线程并不是和Linux线程完全对等的,每个Java线程拥有NEW(新建)、RUNNABLE(就绪)、BLOCKED(阻塞)、WAITING(等待)、TIMED WAITING(计时等待)、TERMINATED(终止)。

Java线程调度属于抢占式调度,线程竞争CPU时间分片来执行,一个线程运行几十毫秒中就处于RUNNING状态,而时间片用完了被剥夺CPU资源又处于READY状态了,等待下次调度。

2 线程状态

在这里插入图片描述
在这里插入图片描述

/**
 * 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;
 }
  1. NEW(新建)
    使用 new Thread(new Runnable) 类或其子类建立一个线程对象后,该线程对象就处于新建状态。

    此时线程还未执行,一般是在构造方法中做一些初始化工作。

    NEW状态的线程只能在thread.start()方法之后转为RUNNABLE状态。

  2. RUNNABLE(就绪)
    NEW状态的线程调用了thread.start()方法之后,该线程就进入RUNNABLE状态,等待JVM里线程调度器的调度,此时处于READY就绪状态。

    当获得CPU时间片后,线程开始执行,线程处于RUNNING运行状态。时间片用完后,线程被剥夺运行资格,等待下一次运行,又变为就绪状态。也就是说,此状态下不能保证线程是就绪还是正在运行。

  3. BLOCKED(阻塞)
    RUNNABLE状态线程申请被其他线程持有的对象锁,此时就转为BLOCKED状态,此时线程不运行任何代码且消耗最少的资源,直到线程调度器重新激活运行该线程。

    当其他线程释放该对象锁后,如果本线程竞争到了对象锁,就转回RUNNABLE状态。

  4. WAITING(无期限等待)
    如果一个线程A等待另一个线程给与调度器一个条件时,线程A进入WAITING状态,等待被其他线程notify唤醒。

    如调用Object.waitThread.joinjava.util.concurrent中的Lock或Condition等。

    条件发生后,就转回RUNNABLE状态。(如果是wait方法进入的等待状态,被notify唤醒后进入对象锁同步队列重新竞争锁,竞争到了就进入RUNNABLE状态,竞争失败就进入BLOCKED状态)

  5. TIMED WAITING(计时等待)
    以上方法有一些带有时间参数的重载方法(如Object.waitThread.joinjava.util.concurrent中的Lock.tryLock、Condition.await),就会进入TIMED WAITING状态

     条件发生后,就转回`RUNNABLE`状态(如果是wait方法进入的等待状态,被notify唤醒后进入对象锁同步队列重新竞争锁,竞争到了就进入RUNNABLE状态,竞争失败就进入BLOCKED状态)。
    
  6. TERMINATED(终止)
    线程run方法结束或抛出了未捕获的异常导致结束。

    在一个TERMINATED的线程上调用start()方法会抛出java.lang.IllegalThreadStateException异常。

3 相关方法

  • Thread.sleep(long millis)
    由当前线程调用此方法,调用后进入TIMED_WAITING状态,但不释放对象锁。millis期满后线程自动唤醒进入RUNNABLE状态。

  • Thread.yield(),
    由当前线程调用此方法,给CPU提示表示当前线程愿意放弃获取的CPU时间片(调度器可忽略该提示),但不释放对象锁。如果成功释放时间片则该线程由运行状态变为就绪状态,由调度器再次选择线程进行调度执行。

    • Sleep对比Yield
      主要是使用场景不同。Sleep主要用来指定睡眠时间让出CPU,并在时间到后再被系统分配CPU资源,进行调度执行;而Yield是用来主动释放CPU给其他线程执行,但无法精确控制是否释放。
  • t.join()/t.join(long millis),
    join方法主要用来等待其他线程运行结束,再继续运行自己的线程代码。

    当前线程里调用其它线程t的join方法,当前线程进入WAITING/TIMED_WAITING状态,当前线程不会释放已经持有的对象锁。

    等到线程t执行完毕或者millis时间到,当前线程重新进入RUNNABLE状态。

  • obj.wait()
    当前线程调用对象的wait()方法,当前线程会释放该对象锁,并进入等待队列等待其他竞争到锁的线程执行完后唤醒,重新进入等待队列进行锁竞争,竞争成功后才会从wait方法返回。

    注意这个wait方法只会让该线程释放当前Object的对象锁,而不会放弃拥有的其他对象锁!

  • obj.wait(mills)
    当前线程调用对象的wait()方法,当前线程会释放该对象锁,并进入等待队列等待其他竞争到锁的线程执行完后唤醒或时间耗尽,重新进入等待队列进行锁竞争,竞争成功后才会从wait方法返回。

    注意这个wait方法只会让该线程释放当前Object的对象锁,而不会放弃拥有的其他对象锁!

  • obj.notify()
    该方法用来任意唤醒一个在对象锁的等待集的线程(其实看了源码会发现不是任意的,而是一个WaitQueue,FIFO)。

  • obj.notifyAll()
    唤醒在此对象Monitor上等待的所有线程。

4 线程优先级

很多操作系统都提供线程优先级的概念,但是由于平台特性的问题,Java中的线程优先级和不同平台中系统线程优先级并不匹配,所以Java线程优先级可以仅仅理解为“建议优先级”,通俗来说就是java.lang.Thread#setPriority(int newPriority)并不一定生效,有可能Java线程的优先级会被系统自行改变。

参考文档

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值