首页 > 编程知识 正文

java线程状态,java线程有哪几种状态

时间:2023-05-05 09:57:02 阅读:200863 作者:3995

线程状态:

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: * 等待线程的线程状态。线程由于调用以下方法之一而处于等待状态: * <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. * 例如:调用了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: * 具有指定等待时间的等待线程的线程状态。由于调用指定正等待时间的以下方法之一,线程处于定时等待状态: * <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

初始状态,线程被构建,但是还没有调用 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获取对象A的锁,正在使用对象A。线程1调用对象A的wait()方法。线程1释放对象A的锁,并马上进入等待队列。锁池里面的对象争抢对象A的锁。线程5获得对象A的锁,进入synchronized块,使用对象A。线程5调用对象A的notifyAll()方法,唤醒所有线程,所有线程进入同步队列。若线程5调用对象A的notify()方法,则唤醒一个线程,不知道会唤醒谁,被唤醒的那个线程进入同步队列。notifyAll()方法所在synchronized结束,线程5释放对象A的锁。同步队列的线程争抢对象锁,但线程1什么时候能抢到就不知道了。 4、同步队列状态 当前线程想调用对象A的同步方法时,发现对象A的锁被别的线程占有,此时当前线程进入同步队列。简言之,同步队列里面放的都是想争夺对象锁的线程。当一个线程1被另外一个线程2唤醒时,1线程进入同步队列,去争夺对象锁。同步队列是在同步的环境下才有的概念,一个对象对应一个同步队列。线程等待时间到了或被notify/notifyAll唤醒后,会进入同步队列竞争锁,如果获得锁,进入RUNNABLE状态,否则进入BLOCKED状态等待获取锁。5、几个方法的比较 Thread.sleep(long millis),一定是当前线程调用此方法,当前线程进入TIMED_WAITING状态,但不释放对象锁,millis后线程自动苏醒进入就绪状态。作用:给其它线程执行机会的最佳方式。Thread.yield(),一定是当前线程调用此方法,当前线程放弃获取的CPU时间片,但不释放锁资源,由运行状态变为就绪状态,让OS再次选择线程。作用:让相同优先级的线程轮流执行,但并不保证一定会轮流执行。实际中无法保证yield()达到让步目的,因为让步的线程还有可能被线程调度程序再次选中。Thread.yield()不会导致阻塞。该方法与sleep()类似,只是不能由用户指定暂停多长时间。thread.join()/thread.join(long millis),当前线程里调用其它线程t的join方法,当前线程进入WAITING/TIMED_WAITING状态,当前线程不会释放已经持有的对象锁。线程t执行完毕或者millis时间到,当前线程一般情况下进入RUNNABLE状态,也有可能进入BLOCKED状态(因为join是基于wait实现的)。obj.wait(),当前线程调用对象的wait()方法,当前线程释放对象锁,进入等待队列。依靠notify()/notifyAll()唤醒或者wait(long timeout) timeout时间到自动唤醒。obj.notify()唤醒在此对象监视器上等待的单个线程,选择是任意性的。notifyAll()唤醒在此对象监视器上等待的所有线程。LockSupport.park()/LockSupport.parkNanos(long nanos),LockSupport.parkUntil(long deadlines), 当前线程进入WAITING/TIMED_WAITING状态。对比wait方法,不需要获得锁就可以让线程进入WAITING/TIMED_WAITING状态,需要通过LockSupport.unpark(Thread thread)唤醒。6、疑问 等待队列里许许多多的线程都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 。

版权声明:该文观点仅代表作者本人。处理文章:请发送邮件至 三1五14八八95#扣扣.com 举报,一经查实,本站将立刻删除。