Java 多线程

Java 多线程 是 Java 并发编程的核心部分,它能充分利用多核 CPU,大幅提升程序的性能和响应能力。下面从零基础到核心知识点,系统梳理 Java 多线程最常用、最重要的内容(基于 JDK 8 ~ JDK 21 的主流实践,2025-2026 视角)。

1. 进程 vs 线程(最基础概念)

对比项进程 (Process)线程 (Thread)
资源分配单位是(有独立的内存空间)否(共享进程的内存)
调度单位是(CPU 调度线程)
创建开销大(创建进程很重)
通信方式进程间通信(IPC:管道、消息队列等)共享内存(更快,但需注意同步)
崩溃影响通常只影响当前进程可能导致整个进程崩溃

一句话总结线程是进程内的轻量级执行单元,现代 Java 程序几乎都是多线程的。

2. Java 中创建线程的几种方式(从基础到推荐)

方式实现方式是否有返回值是否推荐说明与优缺点
1. 继承 Thread 类class MyThread extends Thread不推荐简单,但 Java 单继承,资源浪费
2. 实现 Runnable 接口class MyTask implements Runnable常用推荐,资源复用好,可继承其他类
3. 实现 Callable 接口class MyTask implements Callable<V>常用配合 Future / FutureTask / ExecutorService
4. 使用线程池ExecutorService executor = ...看情况最推荐线程复用、管理成本低、性能最佳
5. Java 21 虚拟线程Thread.ofVirtual().start(runnable)推荐(IO密集)轻量级线程,适合高并发 IO 场景

最推荐的写法(2025-2026 主流)

// 方式1:线程池 + Runnable(最常用)
ExecutorService executor = Executors.newFixedThreadPool(10);
executor.submit(() -> {
    System.out.println("任务执行中... " + Thread.currentThread().getName());
});

// 方式2:线程池 + Callable + Future(带返回值)
Future<String> future = executor.submit(() -> "任务结果");
String result = future.get();   // 阻塞等待结果

// 方式3:Java 21+ 虚拟线程(高并发利器)
Thread virtualThread = Thread.ofVirtual().start(() -> {
    // IO密集任务
});

3. 线程的生命周期(面试必考)

线程有 6 种状态(Thread.State 枚举):

  1. NEW 新创建,还没调用 start()
  2. RUNNABLE 可运行状态(包含 Running 和 Ready)
  3. BLOCKED 等待锁(synchronized 阻塞)
  4. WAITING 无限期等待(wait()、join()、LockSupport.park())
  5. TIMED_WAITING 限时等待(sleep()、wait(timeout)、join(timeout))
  6. TERMINATED 已结束

状态流转图(最常考):

NEW → start() → RUNNABLE ↔ BLOCKED / WAITING / TIMED_WAITING → TERMINATED

4. 线程安全问题三大核心特性(JMM 相关)

特性含义可能出现的问题常见解决方案
原子性一个操作要么全部完成,要么全部不完成i++ 不是原子操作synchronized / Lock / Atomic类
可见性一个线程修改的值,其他线程立刻可见缓存导致不一致volatile / synchronized / Lock
有序性程序执行顺序与代码顺序一致指令重排序volatile / synchronized / Happens-before

Java 内存模型(JMM) 核心作用:保证可见性 + 有序性(原子性靠锁或 Atomic)。

5. 线程同步 / 锁机制对比(面试高频)

机制级别可重入可中断公平锁读写分离适用场景
synchronizedJVM 内置简单场景,代码简洁
ReentrantLockJDK API可选需要中断、超时、公平锁
ReentrantReadWriteLockJDK API可选读多写少(如缓存)
volatile轻量仅保证可见性 + 禁止重排序
AtomicXXXCAS 乐观锁简单计数器、引用
StampedLock (JDK8+)乐观读高性能读写分离场景

synchronized 锁升级(JDK 1.6 后优化):

无锁 → 偏向锁 → 轻量级锁(自旋) → 重量级锁(操作系统 Mutex)

6. 线程池(最重要、最常使用的部分)

四大常用线程池(Executors 工厂创建):

  • newFixedThreadPool:固定线程数
  • newCachedThreadPool:线程数动态伸缩(慎用,OOM 风险)
  • newSingleThreadExecutor:单线程顺序执行
  • newScheduledThreadPool:定时/周期任务

推荐自己创建 ThreadPoolExecutor(7大参数都搞清楚)

ThreadPoolExecutor executor = new ThreadPoolExecutor(
    2,              // corePoolSize
    5,              // maximumPoolSize
    60L,            // keepAliveTime
    TimeUnit.SECONDS,
    new LinkedBlockingQueue<>(100),  // 工作队列
    Executors.defaultThreadFactory(),
    new ThreadPoolExecutor.CallerRunsPolicy()  // 拒绝策略
);

线程池参数记住口诀:核心数 → 最大数 → 存活时间 → 队列 → 线程工厂 → 拒绝策略

7. 常见并发工具(JUC 包)

工具类作用典型使用场景
CountDownLatch倒计数门闩主线程等多个子任务完成
CyclicBarrier循环栅栏多线程相互等待到齐再一起执行
Semaphore信号量(限流)限流、数据库连接池
Exchanger线程间交换数据两个线程交换缓冲区
Phaser分阶段栅栏(比 CyclicBarrier 更灵活)多阶段任务协调
ForkJoinPool分治 + 工作窃取大数据并行计算(如并行排序)

8. 常见面试高频问题(2025-2026 热门)

  1. 线程安全怎么实现?
  2. synchronized 和 ReentrantLock 区别?
  3. volatile 能保证原子性吗?为什么?
  4. 死锁怎么产生?怎么排查?怎么避免?
  5. 线程池参数怎么设置?队列满了怎么办?
  6. 为什么 wait/notify 必须在 synchronized 里?
  7. CAS 原理?ABA 问题怎么解决?
  8. Java 21 虚拟线程了解吗?和传统线程区别?

如果你想深入某一块(比如:线程池参数调优虚拟线程实战JMM 详细锁优化并发容器死锁案例等),可以告诉我,我继续展开讲解 + 代码示例。

希望这份总结对你有帮助!有什么具体想深入的方向吗?

文章已创建 4426

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

相关文章

开始在上面输入您的搜索词,然后按回车进行搜索。按ESC取消。

返回顶部