Java多线程与并发编程全面解析:从基础到高级实践
一、Java多线程基础类
1.1 核心线程类
Java多线程编程的核心类主要包括:
- Thread:线程类,继承Thread类并重写run()方法
- Runnable:函数式接口,实现run()方法,无返回值
- Callable:函数式接口,实现call()方法,有返回值
- Future:异步计算结果接口,用于获取Callable的返回值
1.2 线程状态
Java线程的生命周期包含6种状态:
- NEW:新建状态,线程对象已创建但未启动
- RUNNABLE:可运行状态,包括就绪和运行中
- BLOCKED:阻塞状态,等待获取监视器锁
- WAITING:无限期等待,需要其他线程显式唤醒
- TIMED_WAITING:限期等待,超时后自动唤醒
- TERMINATED:终止状态,线程执行完毕
二、线程池核心机制
2.1 ThreadPoolExecutor
Java线程池的核心实现类,提供灵活的线程池配置:
ThreadPoolExecutor executor = new ThreadPoolExecutor( corePoolSize, // 核心线程数 maximumPoolSize, // 最大线程数 keepAliveTime, // 空闲线程存活时间 TimeUnit.SECONDS, // 时间单位 workQueue, // 阻塞队列 threadFactory, // 线程工厂 handler // 拒绝策略 );2.2 Executors工具类
Executors提供了4种常用的线程池创建方法:
- newFixedThreadPool:固定大小线程池
- newCachedThreadPool:可缓存线程池,自动回收空闲线程
- newSingleThreadExecutor:单线程线程池
- newScheduledThreadPool:定时任务线程池
2.3 ForkJoinPool
专为分治任务设计的线程池,适用于CPU密集型并行计算:
ForkJoinPool pool = new ForkJoinPool(); RecursiveTask<Integer> task = new MyRecursiveTask(data); Integer result = pool.invoke(task);2.4 线程池状态
- RUNNING:正常运行,接受新任务并处理队列任务
- SHUTDOWN:关闭状态,不再接受新任务,继续处理队列任务
- STOP:停止状态,不再接受新任务,不处理队列任务,中断正在执行的任务
- TIDYING:整理状态,所有任务已终止,workerCount为0
- TERMINATED:终止状态,terminated()方法已执行完成
2.5 线程池参数详解
核心参数
- 核心线程数(corePoolSize):线程池保持的最小线程数
- 最大线程数(maximumPoolSize):线程池允许的最大线程数
- 存活时间(keepAliveTime):非核心线程空闲时的存活时间
阻塞队列类型
- ArrayBlockingQueue:基于数组的有界阻塞队列
- LinkedBlockingQueue:基于链表的可选有界阻塞队列
- DelayQueue:基于优先级的延迟队列,元素按到期时间排序
拒绝策略
- AbortPolicy:默认策略,直接抛出RejectedExecutionException异常
- CallerRunsPolicy:由调用者线程执行被拒绝的任务
- DiscardPolicy:直接丢弃被拒绝的任务,不抛异常
- DiscardOldestPolicy:丢弃队列中最旧的任务,然后尝试重新提交当前任务
2.6 线程池执行流程
- 提交任务到线程池
- 如果当前线程数小于核心线程数,创建新线程执行任务
- 如果线程数达到核心线程数,将任务放入阻塞队列
- 如果队列已满且线程数小于最大线程数,创建新线程执行任务
- 如果队列已满且线程数达到最大线程数,执行拒绝策略
三、线程协作方式
3.1 Object类方法
必须在synchronized同步块中使用:
- wait():使当前线程等待,释放对象锁
- notify():随机唤醒一个等待该对象锁的线程
- notifyAll():唤醒所有等待该对象锁的线程
3.2 Thread类方法
- sleep(long millis):使当前线程休眠指定毫秒数,不释放锁
- join():等待目标线程执行完毕
- yield():提示调度器当前线程愿意让出CPU
3.3 ReentrantLock的Condition
提供更灵活的线程等待/通知机制:
ReentrantLock lock = new ReentrantLock(); Condition condition = lock.newCondition(); lock.lock(); try { condition.await(); // 等待 condition.signal(); // 唤醒一个 condition.signalAll(); // 唤醒所有 } finally { lock.unlock(); }四、锁机制
4.1 synchronized关键字
Java内置的同步锁,基于对象监视器实现:
// 同步方法 public synchronized void method() { } // 同步代码块 synchronized (obj) { // 临界区代码 }4.2 AQS(AbstractQueuedSynchronizer)
构建锁和同步器的框架,核心实现包括:
- ReentrantLock:可重入独占锁
- ReentrantReadWriteLock:读写锁,支持读读并发
4.3 CAS(Compare And Swap)
无锁编程的核心技术,通过Unsafe类直接操作内存:
// 原子更新操作 AtomicInteger atomicInt = new AtomicInteger(0); atomicInt.compareAndSet(0, 1); // 比较并交换五、并发协作工具类
5.1 CountDownLatch
计数器,等待多个线程完成:
CountDownLatch latch = new CountDownLatch(3); // 多个线程执行latch.countDown() latch.await(); // 等待计数器归零5.2 CyclicBarrier
循环屏障,让一组线程相互等待,直到所有线程都到达屏障点:
CyclicBarrier barrier = new CyclicBarrier(3, () -> { System.out.println("所有线程已到达屏障,开始执行后续任务"); }); // 线程执行逻辑 Runnable task = () -> { try { // 执行前置任务 System.out.println(Thread.currentThread().getName() + " 到达屏障"); barrier.await(); // 等待其他线程 // 所有线程到达后继续执行 } catch (Exception e) { e.printStackTrace(); } };CyclicBarrier 与 CountDownLatch 对比
| 对比维度 | CountDownLatch | CyclicBarrier |
|---|---|---|
| 核心功能 | 等待一组线程完成各自任务 | 让一组线程相互等待,到达屏障点后继续 |
| 计数器 | 单向递减,不可重置 | 可循环使用,到达屏障后自动重置 |
| 重用性 | 一次性使用,计数器归零后失效 | 可重复使用,支持多轮屏障 |
| 等待方式 | 主线程等待工作线程完成 | 工作线程相互等待 |
| 典型场景 | 启动服务等待依赖初始化完成 | 多阶段并行计算,如多线程数据分片处理 |
| 异常处理 | countDown()不受异常影响 | await()抛出BrokenBarrierException |
使用建议:
- CountDownLatch:适用于一个或多个线程等待其他线程完成特定操作的场景,如服务启动、资源初始化等。
- CyclicBarrier:适用于多个线程需要相互等待,然后同时开始下一阶段任务的场景,如并行计算、多阶段数据处理等。
5.2 Semaphore
信号量,控制并发访问数量:
Semaphore semaphore = new Semaphore(5); // 允许5个并发 semaphore.acquire(); // 获取许可 // 执行临界区代码 semaphore.release(); // 释放许可六、原子操作类
- AtomicInteger:原子整型
- AtomicLong:原子长整型
- AtomicStampedReference:带版本号的原子引用,解决ABA问题
七、异步编程
7.1 Future接口
表示异步计算的结果:
ExecutorService executor = Executors.newSingleThreadExecutor(); Future<String> future = executor.submit(() -> "result"); String result = future.get(); // 阻塞获取结果7.2 CompletableFuture
更强大的异步编程工具,支持链式调用和组合操作:
CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> "Hello") .thenApply(s -> s + " World") .thenAccept(System.out::println);八、并发集合
8.1 ConcurrentHashMap
线程安全的HashMap实现:
- 数据结构:数组 + 链表 + 红黑树
- 锁机制:头结点锁(CAS + synchronized)
- 分段锁优化,提高并发性能
8.2 CopyOnWriteArrayList
写时复制的线程安全List:
- 读操作:无锁,直接读取原数组
- 写操作:加锁(ReentrantLock),复制新数组
- 适用场景:读多写少的并发场景
九、总结
Java多线程与并发编程是Java高级开发的核心技能。掌握线程基础、线程池机制、锁原理、并发工具类和异步编程,能够帮助开发者编写高效、安全的并发程序。在实际开发中,应根据具体场景选择合适的并发工具和策略,平衡性能与复杂度。
