Java线程核心知识总结
一、进程与线程基础
- 进程:操作系统资源分配的最小单位,一个运行的程序就是一个进程,拥有独立内存空间。进程之间相互隔离,切换开销大。
- 线程:进程内的执行单元,CPU调度的最小单位,一个进程可以包含多个线程;共享进程资源,线程切换开销小。
- 多线程:同一个进程内部多条执行路径并发执行,充分利用CPU资源。
- 单核CPU:时间片轮转,宏观并发,微观串行;多核CPU可以实现真正并行。
区别:进程是资源容器,线程是执行任务;进程隔离,线程共享。
二、多线程的优势与问题
✅ 好处
- 提高程序执行效率,充分利用多核CPU;
- 提升响应速度,GUI/服务端不会因为耗时任务卡住。
⚠️ 带来的问题
- 线程安全问题:多个线程同时读写共享变量,会出现数据错乱、bug。
- 示例:多个线程同时修改同一个计数变量,最终结果不符合预期。
- 线程越多≠越快:线程数量过多,线程切换(上下文切换)开销变大,性能反而下降。线程数要合理。
-
线程异常行为: 线程执行过程抛出异常,结果分两种: ① 如果线程内部使用
try‑catch捕获处理异常,线程可以继续执行,完全不会影响其他线程和整个进程。 ② 如果异常没有被捕获,只会导致当前线程终止死亡,其他线程不受影响。JVM 并不会因为单个子线程未捕获异常就直接崩溃;JVM 退出的条件是全部非守护用户线程执行完毕。注意:主线程 main 抛出未捕获异常也只是主线程结束,只要还有其他存活的用户线程,进程依旧继续运行。只有发生底层 JVM 致命错误,或者代码手动调用
System.exit(),才会直接让整个进程崩溃退出InfoQ...。开发坑:主线程的 try‑catch 无法捕获子线程内部抛出的异常;子线程异常不会向上传播到主线程,需要在线程内部处理,或者配置
UncaughtExceptionHandler处理器。
三、Java创建线程的两种基础方式
方式1:继承Thread类
- 类继承
Thread; - 重写
run()方法:线程执行的业务逻辑; - 调用
start()启动线程,不是直接调用run()。run()只是普通方法;start()才会向操作系统申请创建新线程。
class MyThread extends Thread{
@Override
public void run() {
//线程执行代码
}
}
//启动
new MyThread().start();
方式2:实现Runnable接口
- 实现
Runnable接口,重写run; - 把Runnable实例传入Thread构造器;
- 调用
start()启动。推荐Runnable:避免单继承限制,更适合资源共享。
class MyTask implements Runnable{
@Override
public void run() {
//任务逻辑
}
}
new Thread(new MyTask()).start();
四、线程常用API
sleep(long ms):静态方法,让当前线程休眠指定毫秒。✅重点:sleep 仅仅暂停线程运行,不会释放当前线程持有的
synchronized锁。线程抱着锁休眠,其他线程无法获取这把锁,只能阻塞等待,直到同步代码块执行结束锁才释放。⚠️容易混淆:
wait()方法会释放锁;sleep 不会释放锁。- 线程异常:线程运行时异常不会向外抛给main线程,需要线程内部自己捕获处理。
- main线程:程序入口主线程;main结束不代表程序结束,只要还有非守护线程,JVM继续运行。
守护线程 daemon
setDaemon(true)设置为守护线程。- 用户线程:普通业务线程;守护线程:为用户线程服务(GC垃圾回收)。
- 规则:所有用户线程全部结束,JVM直接退出,守护线程直接被终止,不会完整执行完毕。
五、线程状态(生命周期)
- 新建NEW:new Thread(),还没start
- 就绪RUNNABLE:调用start(),等待CPU分配时间片
- 运行RUNNING:抢到CPU时间片,执行run方法
- 阻塞BLOCKED/WAITING/TIMED_WAITING:sleep、等待锁、wait等,让出CPU
- 终止TERMINATED:run执行完毕 / 异常退出,线程结束,不能再次start。
线程一旦结束,不能重启,只能新建线程对象。
六、并发场景:为什么会线程不安全
核心条件同时满足就会线程不安全:
- 多线程环境
- 共享资源(共享变量)
- 对资源进行读写修改操作
案例:多个线程同时修改同一个计数器,最终数值小于预期。 解决思路:加锁synchronized,保证同一时刻只有一个线程执行临界区代码。
七、服务端视角:多线程在服务端的作用
- 服务端程序(如MySQL、Web服务)大量使用多线程;
- 每来一个客户端请求,分配一个线程处理;
- 优势:可以同时处理大量客户端连接;
- 痛点:连接量巨大时,频繁创建销毁线程开销大,引出线程池。
八、总结
- 多线程不是银弹,不是线程开越多速度越快;上下文切换有成本。
- 线程安全是多线程开发最大坑点,只要共享可变数据就要警惕。
start()和run()一定要分清:run只是普通方法,start才真正创建操作系统线程。- 守护线程适合做后台辅助任务,不能用来执行必须完成的业务。
openEuler 是由开放原子开源基金会孵化的全场景开源操作系统项目,面向数字基础设施四大核心场景(服务器、云计算、边缘计算、嵌入式),全面支持 ARM、x86、RISC-V、loongArch、PowerPC、SW-64 等多样性计算架构
更多推荐

所有评论(0)