java线程状态5种与6种说明

线程状态:

  • java线程层面:有6种状态;
  • 操作系统层面: 5种状态。

一、java线程层面线程状态

1、线程状态说明

java线程有6种状态,源码如下:

public class Thread implements Runnable { public enum State {/*** Thread state for a thread which has not yet started.**  当线程被创建出来还没有被调用start()时候的状态。*/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.*  可运行线程的线程状态。 可运行的线程状态正在Java虚拟机中执行,但可能是正在等待操作系统的其他资源如处理器。*/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}.* 线程阻塞等待监视器锁的线程状态。处于阻塞状态的线程在调用{Object.wait}后等待监视器锁进入同步块/方法或重新输入同步块/方法。*/BLOCKED,/*** Thread state for a waiting thread.* A thread is in the waiting state due to calling one of the* following methods:* 等待线程的线程状态。线程由于调用以下方法之一而处于等待状态:* 
    *
  • {@link Object#wait() Object.wait} with no timeout
  • *
  • {@link #join() Thread.join} with no timeout
  • *
  • {@link LockSupport#park() LockSupport.park}
  • *
* **

A thread in the waiting state is waiting for another thread to* perform a particular action.* 处于等待状态的线程正在等待另一个线程执行特定操作。** For example, a thread that has called Object.wait()* on an object is waiting for another thread to call* Object.notify() or Object.notifyAll() on* that object. A thread that has called Thread.join()* is waiting for a specified thread to terminate.* 例如:调用了Object.wait()的线程,正在等待另一个线程调用Object.notify()或Object.notifyAll()。* 调用了Thread.join()的线程正在等待指定的线程终止.*/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:* 具有指定等待时间的等待线程的线程状态。由于调用指定正等待时间的以下方法之一,线程处于定时等待状态:*

    *
  • {@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_WAITING,/*** Thread state for a terminated thread.* The thread has completed execution.* 终止线程的线程状态。线程已完成执行。*/TERMINATED;} }

1)NEW

初始状态,线程被构建,但是还没有调用 start 方法;

2)RUNNABLED

运行状态,JAVA 线程把操作系统中的就绪(ready)运行(running)两种状态统一称为“运行中”

线程对象创建后,其他线程(比如main线程)调用了该对象的start()方法。该状态的线程位于可运行线程池中,等待被线程调度选中,获取CPU的使用权,此时处于就绪状态(ready)。

就绪状态的线程在获得CPU时间片后变为运行中状态(running)。

 注:不一定被调用了start()立刻会改变状态,还有一些准备工作,这个时候的状态是不确定的。

3)BLOCKED

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

阻塞也分为几种情况 :

  • 等待阻塞:运行的线程执行了Thread.sleep() 、wait()、 join() 等方法, JVM 会把当前线程设置为等待状态,当 sleep 结束、join 线程终止或者线程被唤醒后,该线程从等待状态进入到阻塞状态,重新抢占锁后进行线程恢复;

  • 同步阻塞:运行的线程在获取对象的同步锁时,若该同步锁被其他线程锁占用了,那么jvm会把当前的线程放入到锁池中 ;

  • 其他阻塞:发出了 I/O请求时,JVM 会把当前线程设置为阻塞状态,当 I/O处理完毕则线程恢复;

4)WAITING

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

无条件等待,当线程 调用wait()、join()、LockSupport.park() 不加超时时间的方法之后所处的状态,如果没有被唤醒或等待的线程没有结束,那么将一直等待,当前状态的线程不会被分配CPU资源和持有锁;

5)TIME_WAITING

超时等待状态,超时以后自动返回;

有条件的等待,当线程调用 sleep(long)、wait(long)、join(long)、LockSupport.park(long)、LockSupport.parkNanos(long)、LockSupport.parkUntil(long)方法之后所处的状态,在指定的时间没有被唤醒或者等待线程没有结束,会被系统自动唤醒,正常退出。

6)TERMINATED

终止状态,表示当前线程执行完毕 。

执行完了run()方法。其实这只是Java语言级别的一种状态,在操作系统内部可能已经注销了相应的线程,或者将它复用给其他需要使用线程的请求,而在Java语言级别只是通过Java代码看到的线程状态而已。

2、状态转换图

3、等待队列

  • 调用obj的wait(), notify()方法前,必须获得obj锁,也就是必须写在synchronized(obj) 代码段内。
  • 与等待队列相关的步骤和图

  1. 线程1获取对象A的锁,正在使用对象A。
  2. 线程1调用对象A的wait()方法。
  3. 线程1释放对象A的锁,并马上进入等待队列。
  4. 锁池里面的对象争抢对象A的锁。
  5. 线程5获得对象A的锁,进入synchronized块,使用对象A。
  6. 线程5调用对象A的notifyAll()方法,唤醒所有线程,所有线程进入同步队列。若线程5调用对象A的notify()方法,则唤醒一个线程,不知道会唤醒谁,被唤醒的那个线程进入同步队列。
  7. notifyAll()方法所在synchronized结束,线程5释放对象A的锁。
  8. 同步队列的线程争抢对象锁,但线程1什么时候能抢到就不知道了。 

4、同步队列状态

  • 当前线程想调用对象A的同步方法时,发现对象A的锁被别的线程占有,此时当前线程进入同步队列。简言之,同步队列里面放的都是想争夺对象锁的线程。
  • 当一个线程1被另外一个线程2唤醒时,1线程进入同步队列,去争夺对象锁。
  • 同步队列是在同步的环境下才有的概念,一个对象对应一个同步队列。
  • 线程等待时间到了或被notify/notifyAll唤醒后,会进入同步队列竞争锁,如果获得锁,进入RUNNABLE状态,否则进入BLOCKED状态等待获取锁。

5、几个方法的比较

  1. Thread.sleep(long millis),一定是当前线程调用此方法,当前线程进入TIMED_WAITING状态,但不释放对象锁,millis后线程自动苏醒进入就绪状态。作用:给其它线程执行机会的最佳方式。
  2. Thread.yield(),一定是当前线程调用此方法,当前线程放弃获取的CPU时间片,但不释放锁资源,由运行状态变为就绪状态,让OS再次选择线程。作用:让相同优先级的线程轮流执行,但并不保证一定会轮流执行。实际中无法保证yield()达到让步目的,因为让步的线程还有可能被线程调度程序再次选中。Thread.yield()不会导致阻塞。该方法与sleep()类似,只是不能由用户指定暂停多长时间。
  3. thread.join()/thread.join(long millis),当前线程里调用其它线程t的join方法,当前线程进入WAITING/TIMED_WAITING状态,当前线程不会释放已经持有的对象锁。线程t执行完毕或者millis时间到,当前线程一般情况下进入RUNNABLE状态,也有可能进入BLOCKED状态(因为join是基于wait实现的)。
  4. obj.wait(),当前线程调用对象的wait()方法,当前线程释放对象锁,进入等待队列。依靠notify()/notifyAll()唤醒或者wait(long timeout) timeout时间到自动唤醒。
  5. obj.notify()唤醒在此对象监视器上等待的单个线程,选择是任意性的。notifyAll()唤醒在此对象监视器上等待的所有线程。
  6. LockSupport.park()/LockSupport.parkNanos(long nanos),LockSupport.parkUntil(long deadlines), 当前线程进入WAITING/TIMED_WAITING状态。对比wait方法,不需要获得锁就可以让线程进入WAITING/TIMED_WAITING状态,需要通过LockSupport.unpark(Thread thread)唤醒。

6、疑问

  1. 等待队列里许许多多的线程都wait()在一个对象上,此时某一线程调用了对象的notify()方法,那唤醒的到底是哪个线程?随机?队列FIFO?or sth else?Java文档就简单的写了句:选择是任意性的(The choice is arbitrary and occurs at the discretion of the implementation)。

二、操作系统层面线程状态:

​ 很多人会把操作系统层面的线程状态与java线程状态混淆,所以导致有的文章中把java线程状态写成是5种,在此我们说清楚一个问题,java线程状态是6个,操作系统层面的线程状态是5种。如下图所示:

在这里插入图片描述
下面分别介绍一下这5种状态:

1)new :一个新的线程被创建,等待该线程被调用执行;

2)ready :表示线程已经被创建,正在等待系统调度分配CPU使用权,或者时间片已用完,此线程被强制暂停,等待下一个属于它的时间片到来。

3)running :表示线程获得了CPU使用权,正在占用时间片,正在进行运算中;

4)waiting :表示线程等待(或者说挂起),等待某一事件(如IO或另一个线程)执行完,让出CPU资源给其他线程使用;

5)terminated :一个线程完成任务或者其他终止条件发生,该线程终止进入退出状态,退出状态释放该线程所分配的资源。

需要注意的是,操作系统中的线程除去new 和terminated 状态,一个线程真实存在的状态是ready 、running、waiting 。


本文来自互联网用户投稿,文章观点仅代表作者本人,不代表本站立场,不承担相关法律责任。如若转载,请注明出处。 如若内容造成侵权/违法违规/事实不符,请点击【内容举报】进行投诉反馈!

相关文章

立即
投稿

微信公众账号

微信扫一扫加关注

返回
顶部