姚同学 录屏 音乐 摸鱼 压图
线程状态

JDK自定义线程的三种方式及其优缺点

在Java中,创建自定义线程共有三种主要方式,每种方式在扩展性、使用场景及编码复杂度上各有差异。

继承Thread类

优点:实现简单,只需实例化子类即可启动线程。

缺点:由于Java仅支持单继承,若目标类已继承其他类,则无法再采用此方式,扩展性受限。

实现Runnable接口

优点:突破单继承限制,可在实现接口的同时继承其他类;多个线程可共享同一Runnable实例,天然适合“多线程处理同一份资源”的场景。

缺点:构造线程实例需先创建Runnable实现类,再将其包装为Thread,代码步骤相对繁琐。

实现Callable接口

优点:具备Runnable的全部扩展优势,额外支持带返回值的回调,并可声明受检异常,便于上层业务处理执行结果。

缺点:需借助FutureTask或线程池提交,调用链路比Runnable方式复杂。

Java线程状态流转原理

Java将线程生命周期抽象为5种状态,掌握其流转过程是编写可靠并发程序的前提。

1.新建(New)

线程对象已创建,但尚未调用start(),此时仅拥有普通Java对象身份,未与底层OS线程关联。

2.就绪(Runnable)

调用start()后进入就绪状态,表示线程已获得执行资格,等待线程调度器分配CPU时间片。

3.运行(Running)

就绪线程获得时间片即可运行。只有就绪状态能直接进入运行状态;运行过程中可能被抢占,重新变为就绪。

4.阻塞(Blocked)

线程因特定原因主动或被动释放CPU,并暂停执行,直到满足继续条件后再次回到就绪状态。阻塞细分为三类:

等待阻塞:执行Object.wait()、Thread.join()或LockSupport.park(),等待其他线程显式唤醒。

同步阻塞:尝试进入synchronized块/方法时,锁被其他线程占用,进入EntrySet等待。

其他阻塞:执行Thread.sleep(long)、发出阻塞式I/O请求或等待其他JVM级资源,条件满足后自动回到就绪。

5.死亡(Terminated)

线程正常执行完run()/call()方法,或异常抛出而未捕获,生命周期结束,不可再次启动。