09 | Java线程(上):Java线程的生命周期
王宝令
该思维导图由 AI 生成,仅供参考
在 Java 领域,实现并发程序的主要手段就是多线程。线程是操作系统里的一个概念,虽然各种不同的开发语言如 Java、C# 等都对其进行了封装,但是万变不离操作系统。Java 语言里的线程本质上就是操作系统的线程,它们是一一对应的。
在操作系统层面,线程也有“生老病死”,专业的说法叫有生命周期。对于有生命周期的事物,要学好它,思路非常简单,只要能搞懂生命周期中各个节点的状态转换机制就可以了。
虽然不同的开发语言对于操作系统线程进行了不同的封装,但是对于线程的生命周期这部分,基本上是雷同的。所以,我们可以先来了解一下通用的线程生命周期模型,这部分内容也适用于很多其他编程语言;然后再详细有针对性地学习一下 Java 中线程的生命周期。
通用的线程生命周期
通用的线程生命周期基本上可以用下图这个“五态模型”来描述。这五态分别是:初始状态、可运行状态、运行状态、休眠状态和终止状态。
通用线程状态转换图——五态模型
这“五态模型”的详细情况如下所示。
初始状态,指的是线程已经被创建,但是还不允许分配 CPU 执行。这个状态属于编程语言特有的,不过这里所谓的被创建,仅仅是在编程语言层面被创建,而在操作系统层面,真正的线程还没有创建。
可运行状态,指的是线程可以分配 CPU 执行。在这种状态下,真正的操作系统线程已经被成功创建了,所以可以分配 CPU 执行。
当有空闲的 CPU 时,操作系统会将其分配给一个处于可运行状态的线程,被分配到 CPU 的线程的状态就转换成了运行状态。
运行状态的线程如果调用一个阻塞的 API(例如以阻塞方式读文件)或者等待某个事件(例如条件变量),那么线程的状态就会转换到休眠状态,同时释放 CPU 使用权,休眠状态的线程永远没有机会获得 CPU 使用权。当等待的事件出现了,线程就会从休眠状态转换到可运行状态。
线程执行完或者出现异常就会进入终止状态,终止状态的线程不会切换到其他任何状态,进入终止状态也就意味着线程的生命周期结束了。
公开
同步至部落
取消
完成
0/2000
荧光笔
直线
曲线
笔记
复制
AI
- 深入了解
- 翻译
- 解释
- 总结
Java线程的生命周期是多线程编程中的重要概念。本文详细介绍了Java线程的生命周期模型,包括各种状态之间的转换条件和示例,以及Java中线程状态与操作系统线程状态的区别。文章还解释了stop()和interrupt()方法的区别,以及被interrupt的线程如何收到通知。此外,文章强调了理解Java线程生命周期对于诊断多线程Bug的重要性,以及通过jstack命令或Java VisualVM工具导出线程栈信息进行并发问题诊断的重要性。总之,本文对于快速了解Java线程的生命周期及其状态转换机制提供了重要参考,对于学习其他语言的多线程编程也有很大的帮助。
仅可试看部分内容,如需阅读全部内容,请付费购买文章所属专栏
《Java 并发编程实战》,新⼈⾸单¥59
《Java 并发编程实战》,新⼈⾸单¥59
立即购买
© 版权归极客邦科技所有,未经许可不得传播售卖。 页面已增加防盗追踪,如有侵权极客邦将依法追究其法律责任。
登录 后留言
全部留言(122)
- 最新
- 精选
- 姜戈可能出现无限循环,线程在sleep期间被打断了,抛出一个InterruptedException异常,try catch捕捉此异常,应该重置一下中断标示,因为抛出异常后,中断标示会自动清除掉! Thread th = Thread.currentThread(); while(true) { if(th.isInterrupted()) { break; } // 省略业务代码无数 try { Thread.sleep(100); }catch (InterruptedException e){ Thread.currentThread().interrupt(); e.printStackTrace(); } }
作者回复: 👍👍👍
2019-03-1912397 - 虎虎❤️我的一位长辈曾告诉我,没有真正学不会的知识或者技术,只是缺乏好的老师。 有的人可以把复杂的知识讲明白,但是讲解的过程却也是晦涩难懂,不免落了下成。 而学习王老师的课,我一直都觉得很轻松。云淡风轻地就把并发知识抽丝剥茧,确是更显功力。另一方面,我觉得人的大脑更喜欢接受这些平易近人的文字。看似浅近的文字,却更能带领我深入的思考,留下更深刻的印象。反观一些看起来高端大气上档次的论述,让人觉得云山雾罩,好不容易看懂了,但看过后却什么也想不起来了。大概是读文章的时候脑细胞都用来和晦涩的文字做斗争了,已经没有空间去思考和记忆了。 再次感谢王老师给大家带来优秀的课程。
作者回复: 看来我没必要写的很装了😂
2019-03-196122 - Tristan为什么实战高并发程序设计医术中写道“Tread.stop()方法在结束线程时,会直接终止线程,并且会释放这个线程所持有的锁”,而您文中所写的“果线程持有 synchronized 隐式锁,也不会释放”??
作者回复: 是我的错,我确认了一下,隐式锁可以释放。多谢多谢!!!
2019-04-141695 - thasinterrupt是中断的意思,在单片机开发领域,用于接收特定的事件,从而执行后续的操作。Java线程中,(通常)使用interrupt作为线程退出的通知事件,告知线程可以结束了。 interrupt不会结束线程的运行,在抛出InterruptedException后会清除中断标志(代表可以接收下一个中断信号了),所以我想,interrupt应该也是可以类似单片机一样作为一种通知信号的,只是实现通知的话,Java有其他更好的选择。 因InterruptedException退出同步代码块会释放当前线程持有的锁,所以相比外部强制stop是安全的(已手动测试)。sleep、join等会抛出InterruptedException的操作会立即抛出异常,wait在被唤醒之后才会抛出异常(就像阻塞一样,不被打扰)。 另外,感谢老师提醒,I/O阻塞在Java中是可运行状态,并发包中的lock是等待状态。
作者回复: 能和硬件中断联系起来👍👍👍
2019-03-19348 - Junzi当发起中断之后,Thread.sleep(100);会抛出InterruptedException异常,而这个抛出这个异常会清除当前线程的中断标识,导致th.isInterrupted()一直都是返回false的。 InterruptedException - if any thread has interrupted the current thread. The interrupted status of the current thread is cleared when this exception is thrown.
作者回复: 👍
2019-03-26238 - 海鸿如果线程处于阻塞状态(BLOCKED),此时调用线程的中断方法,线程会又如何反应? 是否会像等待状态一样抛异常? 还是会像运行状态一样被标记为已中断状态? 还是不受到任何影响? 麻烦老师解答一下😁
作者回复: 阻塞态的线程不响应中断,并发包里的锁有方法能够响应中断
2019-03-19520 - WhoAmI老师,Java调用阻塞API时,Java层面是runnable,那仍然占用CPU吗,此时此线程在操作系统中是什么状态呢?这个问题好几个人都在问,能详细解释下吗?
作者回复: 不占cpu,操作系统里是阻塞状态。
2019-03-2417 - cky.宇根据接口文档描述,stop()虽然也会中止线程并释放锁,但是没有提供一种补偿的机会,可能某个线程对共享对象进行了不完整的修改,此时如果stop后,该共享对象会继续被其他线程使用,造成线程安全问题。interrupt()则是提供给使用者一种被中断后补偿的机会,例如回滚之前的修改。个人理解是这样的,请老师指点一下。
作者回复: 完全同意!
2019-11-04215 - alias cd=rm -rf思考题,不能中断循环,异常捕获要放在while循环外面
作者回复: 你这也是个办法
2019-03-19513 - J.M.Liu感谢老师提醒,原来jvm层面的线程状态和os层面上的线程状态是不一样的,i/o挂起在jvm也是runable状态。另外并发包的lock其实是处于waitting状态。 但是有个疑问,jvm中blocked状态的线程和waitting状态的线程,除了处在不同的队列之外,还有没有什么区别呀?我这里问的区别包括jvm和os两个层面,谢谢老师
作者回复: block不能响应中断,os里应该都是休眠状态,因为都不能获得cpu使用权
2019-03-19210
收起评论