线程执行完
或者出现异常
(被interrupt那种不算的哈,后续会说)就会进入终止状态,正式走到生命的尽头,没有起死回生的机会
接下来就来看看你熟悉又陌生,面试又经常被问到的Java 线程生命周期吧
[](
)Java语言线程状态
在 Thread 的源码中,定义了一个枚举类 State,里面清晰明了的写了Java语言中线程的6种状态:
-
NEW
-
RUNNABLE
-
BLOCKED
-
WAITING
-
TIMED_WAITING
- TERMINATED
这里要做一个小调查了,你有查看过这个类和读过其注释说明吗?(欢迎留言脚印哦)
耳边响起五环之歌,Java中线程状态竟然比通用线程状态的 5 种多1种,变成了 6 种。这个看似复杂,其实并不是你想的那样,Java在通用线程状态的基础上,有裁剪,也有丰富,整体来说是少一种。再来看个图,注意颜色区分哦
Java 语言中
-
将通用线程状态的
可运行状态
和运行状态
合并为Runnable
, - 将
休眠状态
细分为三种 (BLOCKED
/WAITING
/TIMED_WAITING
); 反过来理解这句话,就是这三种状态在操作系统的眼中都是休眠状态,同样不会获得CPU使用权
看上图右侧【Java语言中的线程状态】,进一步简洁的说,除去线程生死,我们只要玩转 RUNNABLE
和休眠状态
的转换就可以了,编写并发程序也多数是这两种状态的转换。所以我们需要了解,有哪些时机,会触发这些状态转换
远看看轮廓, 近看看细节。我们将上面Java语言中的图进行细化,将触发的节点放到图中 (这看似复杂的图,其实三句话就能分解的,所以别慌),且看:
[](
)RUNNABLE与BLOCKED状态转换
当且仅有(just only)一种情况会从 RUNNABLE 状态进入到 BLOCKED 状态,就是线程在等待 synchronized 内置隐式锁;如果等待的线程获取到了 synchronized 内置隐式锁,也就会从 BLOCKED 状态变为 RUNNABLE 状态了
注意:
上面提到,以操作系统通用状态来看,线程调用阻塞式 API,会变为休眠状态(释放CPU使用权),但在JVM层面,Java线程状态不会发生变化,也就是说Java线程的状态依旧会保持在 RUNNABLE 状态。JVM并不关心操作系统调度的状态。在JVM看来,等待CPU使用权(操作系统里是处在可执行状态)与等待I/O(操作系统是处在休眠状态),都是等待某个资源,所以都归入了RUNNABLE 状态
? —— 摘自《Java并发编程实战》
[](
)RUNNABLE与WAITING状态转换
调用不带时间参数的等待API,就会从RUNNABLE状态进入到WAITING状态;当被唤醒就会从WAITING进入RUNNABLE状态
[](
)RUNNABLE与 TIMED-WAITING 状态转换
调用带时间参数的等待API,自然就从 RUNNABLE 状态进入 TIMED-WAITING 状态;当被唤醒或超时时间到就会从TIMED_WAITING进入RUNNABLE状态
看图中的转换 API 挺多的,其实不用担心,后续分析源码章节,自然就会记住的,现在有个印象以及知道状态转换的节点就好了
相信到这里,你看Java线程生命周期的眼神就没那么迷惑了,重点就是RUNNABLE与休眠状态的切换,接下来我们看一看,如何查看线程中的状态,以及具体的代码触发点
[](
)如何查看线程处在什么状态
[](
)程序中调用 getState()
方法
Thread 类中同样存在 getState()
方法用于查看当前线程状态,该方法就是返回上面提到的枚举类 State
[](
)NEW
就是上面提到, 编程语言中特有的,通过继承 Thread 或实现 Runnable 接口定义线程后,这时的状态都是 NEW
Thread thread = new Thread(() -> {});
System.out.println(thread.getState());
[](
)RUNNABLE
调用了 start()
方法之后,线程就处在 RUNNABLE 状态了
Thread thread = new Thread(() -> {});
thread.start();
//Thread.sleep(1000);
System.out.println(thread.getState());
[](
)BLOCKED
等待 synchronized 内置锁,就会处在 BLOCKED 状态
public class ThreadStateTest {
public static void main(String[] args) throws InterruptedException {
Thread t1 = new Thread(new DemoThreadB());
Thread t2 = new Thread(new DemoThreadB());
t1.start();
t2.start();
Thread.sleep(1000);
System.out.println((t2.getState()));
System.exit(0);
}
}
class DemoThreadB implements Runnable {
@Override
public void run() {
commonResource();
}
public static synchronized void commonResource() {
while(true) {
}
}
}
[](
)WAITING
调用线程的 join()
等方法,从 RUNNABLE 变为 WAITING 状态
public static void main(String[] args) throws InterruptedException {
Thread main = Thread.currentThread();
Thread thread2 = new Thread(() -> {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
e.printStackTrace();
}
System.out.println(main.getState());
});
thread2.start();
thread2.join();
}
[](
)TIMED-WAITING
调用了 sleep(long)
等方法,线程从 RUNNABLE 变为 TIMED-WAITING 状态
public static void main(String[] args) throws InterruptedException {
Thread thread3 = new Thread(() -> {
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
// 为什么要调用interrupt方法?
Thread.currentThread().interrupt();
e.printStackTrace();
}
});
thread3.start();
### 最后
我的面试经验分享可能不会去罗列太多的具体题目,因为我依然认为面试经验中最宝贵的不是那一个个具体的题目或者具体的答案,而是结束面试时,那一刻你的感受以及多天之后你的回味~
**很多人在刚接触这个行业的时候或者是在遇到瓶颈期的时候,总会遇到一些问题,比如学了一段时间感觉没有方向感,不知道该从那里入手去学习,对此我整理了一些资料,需要的可以免费分享给大家**
在这里小编分享一份自己收录整理上述技术体系图相关的几十套**腾讯、头条、阿里、美团等公司的面试题**,把技术点整理成了视频和PDF(实际上比预期多花了不少精力),包含**知识脉络 + 诸多细节**,由于篇幅有限,这里以图片的形式给大家展示一部分。
**[CodeChina开源项目:《Android学习笔记总结+移动架构视频+大厂面试真题+项目实战源码》](https://ali1024.coding.net/public/P7/Android/git)**
**【Android核心高级技术PDF文档,BAT大厂面试真题解析】**
![](https://s2.51cto.com/images/20210913/1631471889440409.jpg)
**【算法合集】**
![](https://s2.51cto.com/images/20210913/1631471889162449.jpg)
**【延伸Android必备知识点】**
![](https://s2.51cto.com/images/20210913/1631471889289339.jpg)
**【Android部分高级架构视频学习资源】**
**Android精讲视频领取学习后更加是如虎添翼!**进军BATJ大厂等(备战)!现在都说互联网寒冬,其实无非就是你上错了车,且穿的少(技能),要是你上对车,自身技术能力够强,公司换掉的代价大,怎么可能会被裁掉,都是淘汰末端的业务Curd而已!现如今市场上初级程序员泛滥,这套教程针对Android开发工程师1-6年的人员、正处于瓶颈期,想要年后突破自己涨薪的,进阶Android中高级、架构师对你更是如鱼得水,赶快领取吧!
原创文章,作者:3628473679,如若转载,请注明出处:https://blog.ytso.com/150561.html