线程的状态

线程状态:新建、就绪、运行、阻塞、死亡。

新建:创建后未start()。
就绪:start()后,未获CPU。
运行:获CPU执行run()。
阻塞:wait()、锁等待、sleep()。
死亡:run()完或异常。

关键点:
wait()释放锁,需synchronized。

sleep()不释放锁,Thread方法。

notify()随机唤醒,notifyAll()全唤醒。

转换: NEW -> start() -> RUNNABLE。
RUNNABLE -> CPU -> RUNNING。
RUNNING -> time片/yield() -> RUNNABLE。
RUNNING -> wait/sleep/I/O -> BLOCKED。
BLOCKED -> 唤醒/超时/I/O完 -> RUNNABLE。
RUNNING -> 完/异常 -> TERMINATED。

别这么干:用suspend(),易死锁。

实操提醒:用isAlive()检查线程状态。

java线程的六大状态分别是什么

说实话,讲Java线程状态这事儿,我得先从当年踩坑的经历说起。
记得刚接触多线程那会儿,对着堆栈溢出和死锁一脸懵逼,老板说"先搞懂状态转换",我直接把那六种状态画成流程图,结果发现越画越复杂,越看越像绕圈子。

NEW状态其实挺直观的。
我当年写个简单的线程池测试,new Thread(() -> System.out.println("Hello")).start(); 这行代码一写,线程就乖乖待在JVM内存里,像刚出生的婴儿没吃饱奶似的,没CPU时间片就动弹不得。
直到start()被调用,它才变成RUNNABLE,这时候就分两种情况——要么在就绪队列里排着队等CPU,要么突然被选中的那一刻开始跑run方法,跑得快的时候能看见run里打印的日志像闪电一样闪过。

有意思的是RUNNABLE里的就绪状态。
我有个项目用线程池处理大量IO操作,结果发现CPU一直被几个线程霸占着,后来发现是忘了调用Thread.yield()。
调了之后CPU负载骤降,老板还夸我懂"谦让"呢。
但要注意,yield()不是让出CPU就立刻变阻塞的,它只是把当前线程从运行态改到就绪态,相当于在食堂排队时说"我去上个厕所",等会儿可能又回来抢位置。

BLOCKED状态最常见的是锁竞争。
我上次重构一个老系统时,发现有个同步方法加了八层synchronized,线程A进去后,B/C/D/E/F/G/H只能干瞪眼。
这种时候看JVM监控台,那些线程CPU占用率是0,像被施了定身咒。
直到A跑完方法释放锁,这些线程才"嗖"地一下全变成就绪态,争抢CPU资源像抢春运火车票。

WAITING和TIMED_WAITING的区别是精髓所在。
我写个定时任务用Thread.sleep(1 000),这线程就乖乖睡一秒。
但用Object.wait(1 000),它会在等待一秒后自动醒来,前提是有人调用notify/notifyAll或者锁被其他线程释放。
有个坑是我踩过,把wait写在synchronized外面,结果线程直接抛异常,因为wait必须在持有锁的情况下才能调用。
这种细节没注意到,调试能让人头发变白。

说到TERMINATED状态,我有次写了个线程监听网络端口,忘了捕获Exception,结果线程突然中断,我花半天时间才在日志里找到个诡异的"java.net.SocketException: Connection reset",最后才发现是那个没捕获的异常把线程"杀死"了。
这种时候线程就彻底消失了,JVM会自动回收资源,就像你删了个APP,图标没了但内存还在。

最烦的是锁对象必须一致这个规则。
我有个同学写代码时把wait和notifyAll分开放,结果运行时总崩,他说"明明同步代码块一样啊"。
后来发现他wait用的是this.wait(),notifyAll是class对象调用的。
这种时候记住,wait/notify这对是成双成对的,就像钥匙和锁孔,搞混了永远打不开。

状态转换这些机制,说实话,不是看懂就能掌握的。
得像玩俄罗斯方块那样,看多了自然就摸清CPU调度、锁竞争这些"游戏规则"。
我现在的习惯是写完线程代码,先画个状态转换图,标清楚哪些方法能进哪些状态,再运行监控台看看线程轨迹对不对。
有时候看着监控台里那些线程像过山车一样切换状态,还挺有意思的。

java线程有几种状态

Java线程状态多,新建、就绪、运行、阻塞、死亡,新建无资源,就绪等CPU,运行忙任务,阻塞等条件,死亡结束或强制停。

基于java 线程的几种状态

嗨,上次有个客人问我关于Java线程状态的问题,我就给他详细解释了一下。
Java线程的状态确实挺有意思的,我来给你简单梳理一下。

首先,线程有五种状态:
1 . 新建(new):这个状态很简单,就是创建了线程对象,但还没启动它。

2 . 可运行(Runnable):线程对象创建后,调用start()方法或者线程在可运行线程池中等待,就有机会获取CPU的使用权。

3 . 运行(Running):线程获取了CPU的使用权,开始执行程序代码。

4 . 阻塞(Blocked):这个状态有点复杂,线程可能因为以下几种原因放弃CPU使用权:
等待阻塞:线程调用wait()方法,它会进入等待队列。

同步阻塞:线程尝试获取同步锁,但锁被其他线程占用,它会进入锁池等待。

其他阻塞:线程执行sleep()或join()方法,它会进入阻塞状态。
比如sleep()超时或者join()等待的线程结束了,它就会进入可运行状态。

5 . 死亡(Dead):线程执行完毕,或者因为异常退出run()方法,生命周期就结束了。

其实,理解这些状态的关键在于知道线程是如何在不同状态之间转换的。
比如,一个线程从运行状态进入阻塞状态,通常是因为它需要等待某些资源或事件,比如锁、条件变量或者其他线程的完成。

所以,下次有人问你Java线程的状态,你就可以这样回答了。
反正你看着办,如果还有其他问题,我还在想这个问题呢。
😄