这篇文章主要介绍“java线程有多少种状态”,在日常操作中,相信很多人在java线程有多少种状态问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”java线程有多少种状态”的疑惑有所帮助!接下来,请跟着小编一起来学习吧!
人有生老病死。同样的,线程有自己的生命周期。在 Java 中线程的生命周期中一共有 6 种状态:
New(新创建)
Runnable(可运行)
Blocked(被阻塞)
Waiting(等待)
Timed Waiting(计时等待)
Terminated(被终止)
查看 Thread 类的源码时,内部还定义了这样一个枚举类。这个枚举类定义的就是线程的状态,源码如下:
public enum State { NEW, RUNNABLE, BLOCKED, WAITING, TIMED_WAITING, TERMINATED; }
PS:线程在任何时刻只可能处于以上 6 种的其中 1 种状态,我们可以调用 getState () 查看线程的状态。
我们知道线程有 6 种状态。然而,它是如何切换的呢?狗哥根据自己的理解做了一张图,接下来将根据这张图详细了解下线程状态的切换。
线程的 6 种状态
先注意 NEW 状态:线程被 NEW 出来,但还没调用 start 方法时,就处于这种状态。一旦调用了 start 方法也就进入了 RUNNABLE 状态。
处于 RUNNABLE 的线程,比较特殊。它还分两种状态:Running 和 Ready。也就是说,Java 中处于 Runnable 状态的线程有可能正在执行,也有可能没有正在执行,正在等待被分配 CPU 资源。
因此,我们可以推断出,一个处于 Runnable 状态的线程,当它运行到任务的一半时,执行该线程的 CPU 被调度去做其他事情,则该线程暂时不运行。但是,它的状态依然不变,还是 Runnable,因为它有可能随时被调度回来继续执行任务。
也就是说:处于 Runnable 状态的线程并不一定在运行。这点在面试中常问,小伙伴们要注意了。
再来看看最简单的 Blocked 状态,从 Runnable 进入 Blocked 只有一种可能:就是进入 synchronized 关键字保护的代码,但是没有获取到 monitor 锁。
线程的 6 种状态
再来,看图的右侧,Blocked ----> Runnable 状态:当处于 Blocked 状态的线程获取到锁。
线程从 Runnable 进入 Waiting 状态,有三种可能性:
没有设置 Timeout 参数的 Object.wait () 方法。
没有设置 Timeout 参数的 Thread.join () 方法。
LockSupport.park () 方法。
上面我们知道,线程进入 Blocked 状态只可能是:进入 synchronized 保护的代码,但是没获取到 monitor 锁。然而,Java 中还有很多锁,比如:ReentrantLock。线程在获取这种锁时,没有抢到就会进入 Waiting 状态,因为它本质上是调用了 LockSupport.park () 方法。
同样的,调用 Object.wait () 和 Thread.join () 也会让线程进入等待状态。
Blocked 与 Waiting 的区别是:Blocked 在等待其他线程释放 monitor 锁,而 Waiting 则是在等待某个条件,比如 join 的线程执行完毕,或者是 notify ()/notifyAll ()。
线程的 6 种状态
看 Waiting 右侧,Waiting ----> Runnable:1、当执行了 LockSupport.unpark (),2、join 的线程运行结束,3、被中断
看 Waiting 右侧,Waiting ----> Blocked:我们看图可以知道其他线程调用 notify () 或 notifyAll () 来唤醒处于 Waiting 的线程,它会直接进入 Blocked 状态。这是为什么?
其他线程能调用 notify () 或 notifyAll () 试图唤醒 Waiting 状态线程,说明必须持有同一个 monitor 锁,也就是说处于 Waiting 的线程被唤醒后并不能马上抢到 monitor 锁,所以它必须先进入 Blocked 状态。而唤醒它的线程执行完毕释放锁后,它能抢到锁就从 Blocked 进入 Runnable 状态。
这种状态与 Waiting 状态的区别在于:有没有时间限制,Timed Waiting 会等待超时,由系统自动唤醒,或者在超时前被唤醒信号唤醒。
有以下 5 种情况会让线程进入 Timed Waiting 状态:
设置 Timeout 参数的 Thread.sleep (time) 方法。
设置 Timeout 参数的 Object.wait (time) 方法。
设置 Timeout 参数的 Thread.join (time) 方法。
设置 Timeout 参数的 LockSupport.parkNanos (long nanos) 方法。
设置 Timeout 参数的 LockSupport.parkUntil (long deadline) 方法。
线程的 6 种状态
看 Timed Waiting 右侧,Timed Waiting ----> Blocked:跟 Waiting 一样,其他线程执行 notify () 和 notifyAll (),当前线程也是先进入 Blocked 状态,而后视锁的获取情况再决定是否进入 Runnable 状态。
另外,Timed Waiting ----> Runnable :1、当前线程的超时时间到了且能直接获取到锁,2、join 的线程运行结束,3、被中断,4、调用了 LockSupport.unpark (),这几种情况会直接恢复到 Runnable,而无需经历 Blocked 状态。
最后一种,想要进入终止状态就比较简单了,有三种情况:
任务执行完毕,线程正常退出。
出现一个没有捕获的异常(比如直接调用 interrupt () 方法)。
到此,关于“java线程有多少种状态”的学习就结束了,希望能够解决大家的疑惑。理论与实践的搭配能更好的帮助大家学习,快去试试吧!若想继续学习更多相关知识,请继续关注亿速云网站,小编会继续努力为大家带来更多实用的文章!
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。