java线程状态和状态切换

背景

          先来探讨一个关于多线程的基础知识:java线程有多少种状态?根据JDK定义,答案是六种!为什么很多人给出的答案却是五种呢?这极有可能是将操作系统层面的线程状态和java线程状态混为一潭了。因为,小编在翻阅JDK源码的基础上,介绍一下java线程的六种状态以及操作系统层面的五种状态。

java线程状态

          JDK中声明了六种java线程状态,以枚举的形式定义在Thread.State中,而且注释开篇撇清了和操作系统层面线程状态的关系-----【这些是状态是虚拟机状态,不反映任何操作系统的线程状态】,英文原文描述如下:

简单来介绍一下这六种状态。

1.new:新建状态,新创建一个线程对象时的初始状态,此时尚未调用start()方法。

2.runnable:就绪状态,Java线程把操作系统中的就绪和运行两种状态统一称为“就绪状态或者可运行状态”。英文相关描述如下:

A thread in the runable state is executing in the Java virtual machine but it may be waiting for other resources from the operation system such as processor.

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

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

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

4. waiting: 等待时间,没有超过时间,要被其他线程或者有其他的中断操作;即一个正在无限期等待另一个线程执行一个特别的动作的线程处于waiting状态,英文原文如下:

A thread that is waiting indefinitely for another thread to perform a particular action is in the state.

一个线程进入waiting 状态是因为调用了方法Object.wait(),Thread.join()或者LockSupport.park()。然后会等其他线程执行一个特别的动作,比如:

  •   一个调用了Thread.join方法的线程会等待指定的线程结束。
  • 一个调用了某个对象的wait方法的线程会等待另一个线程调用此对象的notify()或notifyAll()。

5.Time_waiting:等待超时,超过以后会自动返回;如下方执行超时,就会进入超时等待状态:Thread.sleep(long),Object.wait(long),Thread.join(long),LockSupport.park(long),LockSupport.parkNanos(long),LockSupport.parkUntil(long)。

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

我们可以通过getState()来查看线程的当前状态:

线程状态间的转换

          借一个图来描述:

关于具体的转换场景,图中描述的比较清楚,此处不在赘述。注意:

  1. sleep,join,yieId时并不释放对象锁资源,而执行函数wait()时会释放锁,对象在被notif/notifyAll唤醒时,重新去抢夺获取对象锁资源。
  2. sleep可以在任何地方使用,而wait,notify,notifyAll只能在同步方法或者同步块中使用。
  3. 调用obj.wait()会立即释放锁,以便其他线程可以执行notify,但notify()不会立刻释放sycronized(obj)中的对象锁,必须要等notify()所在线程执行完同步方法或者同步块才会释放这把锁,然后供线程等待池的线程来抢夺对象锁。 wait方法是Object的方法,线程释放锁,进入waiting或timed_waitind 状态,等待时间到了或被 notif/notifyAll唤醒后回去竞争锁,如果获得锁,进入runnable,否则进入阻塞状态等待获取锁。

操作系统层面线程状态

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

下面分别介绍一下这五种状态:

  1. new :一个新的线程被创建,等待该线程被调用执行。
  2. ready:表示线程已被创建,正在等待系统调度分配CPU使用权或者时间片已用完,此线程被强制暂停,等待下一个属于它的时间片到来。
  3. running:表示线程获得了CPU使用权,正在占用时间片。
  4. waiting:表示线程等待(或者说挂起),等待某一事件(如IO或另一个线程)执行完,让出CPU资源给其他线程使用。
  5. terminated:一个线程完成任务或者其他终止条件发生,该线程终止进入退出状态,退出状态释放该线程所分配的资源。

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

Thread.State中的Runnable状态涵盖了操作系统层面的【可运行状态】,【运行状态】和【阻塞状态】(由于BIO导致的线程阻塞,在java里无法区分,仍然认为是可运行,就好比我们在run()方法里调用IO方法,再者虽然有线程上下文切换但在JAVA层面还是运行的)。

至此,我们就把java线程状态以及操作系统层面的线程就理清了,喜欢的小伙伴可以关注我呀

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值