java线程几种状态介绍

Java 的五个主要状态很简单: 1 .New:线程刚刚创建,尚未启动。
2 . Ready:启动,等待CPU资源。
3 .运行:获取CPU并运行代码。
4 、阻塞:等待资源或条件,如sleep()、wait()。
5 、死亡:执行完毕或非正常终止。

状态转换由 JVM 自动进行,并使用调用方法的机制。
块并不意味着序列的结束,而是准备意味着等待CPU。
不要使用 suspend() 和resume(),使用 traps()/notify() 或 lock。
如需更深入的教程,您可以查看 Java 并发编程教程。

阻塞状态与等待状态有什么不同

阻塞状态和等待状态是两个很容易混淆的概念。
我们分开来说吧。

阻塞条件,这通常是被动输入的。
例如,如果你考虑一下Java,如果一个线程争夺锁并且未能赢得它,它将自动进入阻塞状态。
我记得在项目中,我们使用了ReentrantLock。
某些线程不获取锁,只是挂在那里。
CPU不会为其分配时间片,直到锁被释放后才会继续运行。
这是正常的被动阻挡。

至于等待状态,则更加主动。
线程调用自己的wait方法,进入等待状态。
刚开始学习多线程的时候,我看到代码中到处都是wait,还以为是某种神奇的方法。
然后我发现需要在一个同步代码块中调整,等待另一个线程发送通知信号后再继续。
我记得曾经写过一个生产者-消费者的例子。
用户不断调用await,却忘记将其放入synchronized块中,从而报错。
我花了很长时间。

同步机制也可以清晰地看到。
阻塞状态与同步无关,但等待状态必须处于同步环境中。
就像使用notifyAll唤醒时一样,必须在持有锁的同步方法中调用。
记得一篇关于Java并发的博文,强调了这一点,说如果不在同步块中等待,CPU一调度就会出现异常。

对于CPU调度,不要认为在任何情况下都能工作并且不给出CPU时间扣除。
但等待状态有它的特点。
它在同步代码块中等待,等待另一个线程通知。
这与逻辑只是等待资源的阻塞状态不同。

坦白说,阻塞是被动的,等待资源; wait 处于活动状态,等待其他人发送信号。
只要看清楚这一点就可以了。

线程的几种状态

说实话,谈论线程状态确实让我刚入行的时候很头疼。
但如果你仔细想想,其实还蛮有趣的。
以 Windows 1 1 上的 Lenovo Savior Y9 000P 配置为例。
当您想到具有多个核心和多个线程运行的 CPU 的形象时,您确实需要知道如何做到这一点。

新状态?在我看来,我刚写完启动方法,线程还挂在那里,就像你刚点了外卖,司机还没出门一样。
可运行状态更加活跃,抢占时间段就像抢占双十一折扣一样。
我有一个使用Java 来使用多线程修改文件的项目。
你能相信吗? CPU 使用率立即上升到 9 0% 以上,此时尤为明显 - 多个可运行线程正在轮流运行。

被阻止状态?这种情况经常发生。
我之前执行过数据库操作,线程A想要修改表。
结果锁被线程B持有,A只能处于阻塞状态。
当线程 B 用完并重置时,A 立即变得可运行。
我亲眼看到了这一点。
在代码更改过程中,JProfiler 检查了它,瞧!许多线程被阻塞在那里。

最令人惊奇的是Waiting和Time_Waiting。
了解这两者之间的区别非常重要。
我有一个同事写C语言并使用Monitor.Wait()来完成耗时的任务。
然而,他忘记使用WaitTimeout,线程等待了很长时间。
根据系统日志,处于Time_Waiting状态,直到内存溢出才会被系统终止。
我当时就一头雾水,后来发现两者之间有一个超时设置。

完成状态?说白了:线程结束了。
我正在编写一个Python脚本来处理数据并在执行后自动退出。
那么脚本中的线程当然就终止了。
但需要注意的是,线程的结束并不意味着资源会立即释放。
这取决于操作系统的规划。

说到线程和进程的关系,我有点偏激了。
Linux中明确区分了用户线程和内核线程,而Windows是内置的,但是内核线程和用户线程都可以使用。
我测试使用C1 1 标准编写线程库并在Y9 000P上运行。
虽然共享内存速度很快,但单独的调用堆栈的优点是,如果你使用多个线程来更改内存,整个进程不会崩溃——除非你写得太离谱。

在多核CPU上使用多线程,效果立即可见。
我有一个图像处理项目,单线程运行需要半天时间。
切换到多线程后,Y9 000P 上可以在几秒钟内获得结果。
但是,请注意,线程越多并不总是越好。
我尝试同时运行 2 00 个线程来转换视频。
这将 CPU 利用率推至 8 5 %,但磁盘 I/O 却无法跟上。
最终还是比单线程慢。
我自己没有运行过这个,但是我从数据中记得当线程数是CPU核心数的1 .5 倍时系统开销显着增加超过。

Linux中POSIX线程和Windows线程最大的区别在于信号处理。
当我最初编写跨平台代码时,我遇到了一个陷阱。
在Linux上,信号可以直接杀死线程,但在Windows上你需要使用SetThreadAffinityMask手动隔离它们。
这给我留下了深刻的印象,我花了将近一周的时间才弄清楚。

超线程确实很有趣。
像Y9 000P这样的CPU表面上有8 个核心,但实际上可以有1 6 个线程。
我对渲染任务进行了测量,发现开启HT后,性能提升了1 5 %,但CPU温度也升高了1 0度。
就像挤进地铁一样。
表面上有8 辆推车,但实际上可以塞1 0辆——但不要真的尝试,安全第一。

最后说一个小知识:Windows线程的内核对象是ESSENCE_HEADER,该结构体中有一个ContextSwitchTime,用于记录切换开销。
这个东西对于系统性能分析特别有用,但是9 9 %的开发者根本不用它。
老实说,该文档给我留下了深刻的印象,我终于记住了时间戳字段。

java线程有几种状态

这是一个危险。
线程状态变化比较复杂,处理不当很容易导致死锁。

实用提醒:线程状态改变要高效,合理使用同步机制。