Java并发编程核心知识点笔记
(线程池 | 异步回调 | synchronized/volatile 整合版)
本文整合线程池核心原理、无/有参异步回调、Java同步关键字的核心知识点,搭配可运行示例,用于本地温习,覆盖日常开发与面试高频考点。
一、Java线程池(SpringBoot 实践)
线程池是管理线程的核心工具,避免频繁创建/销毁线程,提升并发性能,核心遵循「核心线程→队列→最大线程→拒绝策略」的工作流程。
1.1 核心参数与工作流程
| 参数名 |
含义 |
核心作用 |
| corePoolSize |
核心线程数(长期存活,默认不销毁) |
线程池基础处理能力 |
| maximumPoolSize |
最大线程数(核心+非核心线程总和) |
并发处理能力上限 |
| queueCapacity |
任务队列容量(存储等待执行的任务) |
缓冲突发流量,避免频繁创建线程 |
| keepAliveTime |
非核心线程空闲超时时间(超时自动销毁) |
释放空闲资源 |
| rejectedExecutionHandler |
拒绝策略(线程池满载时的兜底方案) |
保护系统不被压垮 |
工作流程:
提交任务 → 核心线程未满?创建核心线程 → 核心线程满?任务入队列 → 队列满?创建非核心线程 → 最大线程满?触发拒绝策略。
1.2 SpringBoot 线程池配置
基于 ThreadPoolTaskExecutor 封装,替代默认线程池,生产环境推荐配置:
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.scheduling.annotation.EnableAsync; import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor; import java.util.concurrent.ThreadPoolExecutor;
@Configuration @EnableAsync public class ThreadPoolConfig { @Bean("customThreadPool") public ThreadPoolTaskExecutor customThreadPool() { ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor(); executor.setCorePoolSize(5); executor.setMaxPoolSize(10); executor.setQueueCapacity(20); executor.setKeepAliveSeconds(60); executor.setThreadNamePrefix("custom-thread-"); executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy()); executor.initialize(); return executor; } }
|
1.3 线程池基础使用(无回调异步任务)
无回调异步任务:提交后主线程不等待、不获取结果,适用于日志、通知等无需结果的场景。
import org.springframework.scheduling.annotation.Async; import org.springframework.stereotype.Service;
@Service public class AsyncTaskService { @Async("customThreadPool") public void noCallbackTask(String taskName) { System.out.println(Thread.currentThread().getName() + " 执行无回调任务:" + taskName); try { Thread.sleep(1000); } catch (InterruptedException e) { Thread.currentThread().interrupt(); } } }
|
二、异步回调(无参回调 vs 有参回调)
异步回调解决「无回调任务无法获取结果、处理异常」的问题,分为无参回调(仅通知完成,无参数)和有参回调(接收任务结果/异常,核心场景),基于 CompletableFuture 实现。
2.1 核心概念
- 无参回调:任务完成后触发回调,回调函数无参数,仅做简单通知;
- 有参回调:任务完成后触发回调,回调函数接收任务结果(成功)或异常信息(失败),支持结果处理、链式逻辑。
2.2 无参回调实现
适用于仅需通知任务完成,无需处理结果的场景:
import org.springframework.stereotype.Service; import java.util.concurrent.CompletableFuture; import java.util.concurrent.Executor; import javax.annotation.Resource;
@Service public class CallbackService { @Resource(name = "customThreadPool") private Executor threadPool;
public void noParamCallback() { CompletableFuture.runAsync(() -> { System.out.println(Thread.currentThread().getName() + " 执行异步任务"); try { Thread.sleep(1000); } catch (InterruptedException e) {} }, threadPool) .thenRun(() -> System.out.println("无参回调:任务执行完成")) .exceptionally(ex -> { System.out.println("无参回调:任务执行异常"); return null; }); } }
|
2.3 有参回调实现(核心)
适用于需要处理任务结果、异常的场景,是生产环境主流用法,结合 @Async 整合Spring生态:
步骤1:异步任务返回 CompletableFuture
@Service public class AsyncCallbackService { @Async("customThreadPool") public CompletableFuture<String> withParamTask(String username) { try { Thread.sleep(1000); String result = "用户【" + username + "】注册成功,ID:" + System.currentTimeMillis(); return CompletableFuture.completedFuture(result); } catch (Exception e) { return CompletableFuture.failedFuture(new RuntimeException("注册失败:" + e.getMessage())); } } }
|
步骤2:绑定有参回调(接收结果/异常)
import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RestController; import javax.annotation.Resource; import java.util.concurrent.CompletableFuture;
@RestController public class CallbackController { @Resource private AsyncCallbackService asyncCallbackService;
@GetMapping("/register") public String register(String username) { CompletableFuture<String> future = asyncCallbackService.withParamTask(username);
future.thenAccept(result -> { System.out.println("有参回调(成功):" + result); }) .exceptionally(ex -> { System.out.println("有参回调(失败):" + ex.getMessage()); return null; });
return "注册请求已提交,后台异步处理中..."; } }
|
2.4 进阶:链式有参回调
多个异步任务依赖前序结果时,用链式回调实现线性逻辑(类JS async/await 思维):
CompletableFuture.supplyAsync(() -> "用户ID:1001", threadPool) .thenApply(userId -> { System.out.println("为" + userId + "发送注册短信"); return userId + ":短信发送成功"; }) .thenAccept(smsResult -> { System.out.println(smsResult + ",更新用户状态为已激活"); }) .exceptionally(ex -> { System.out.println("流程异常:" + ex.getMessage()); return null; });
|
三、Java同步关键字:synchronized & volatile
解决多线程下共享变量的可见性、原子性、有序性问题,是并发编程的基础,日常开发虽被框架封装,但底层原理必须掌握。
3.1 volatile 关键字(轻量级无锁)
核心特性
- 保证可见性:一个线程修改共享变量,其他线程立即看到最新值(不读线程缓存);
- 禁止指令重排:JVM不打乱代码执行顺序,避免多线程逻辑混乱;
- 不保证原子性:复合操作(如
i++)用volatile仍会出错,仅适用于「一写多读」场景。
适用场景
线程状态标记、单例双重检查、开关控制等「一个线程写,多个线程读」的场景。
示例:volatile 控制线程停止
public class VolatileDemo { private static volatile boolean isRunning = true;
public static void main(String[] args) throws InterruptedException { new Thread(() -> { while (isRunning) {} System.out.println("子线程停止成功"); }).start();
Thread.sleep(1000); isRunning = false; System.out.println("主线程已修改状态"); } }
|
3.2 synchronized 关键字(重量级内置锁)
核心特性
- 保证原子性:加锁代码同一时间仅一个线程执行,复合操作不被打断;
- 保证可见性:释放锁时刷回主内存,加锁时读取最新值;
- 保证有序性:加锁代码按顺序执行,禁止指令重排;
- 缺点:加锁/解锁有开销,竞争线程会阻塞(悲观锁)。
适用场景
多线程修改共享资源、计数器、库存扣减、共享集合操作等「多线程竞争写」场景。
示例:synchronized 保证计数器安全
public class SynchronizedDemo { private static int count = 0;
private static synchronized void increment() { count++; }
public static void main(String[] args) throws InterruptedException { Thread[] threads = new Thread[10]; for (int i = 0; i < 10; i++) { threads[i] = new Thread(() -> { for (int j = 0; j < 1000; j++) { increment(); } }); threads[i].start(); }
for (Thread thread : threads) { thread.join(); }
System.out.println("最终计数:" + count); } }
|
3.3 核心区别对比
| 对比维度 |
volatile |
synchronized |
| 核心作用 |
可见性、禁止重排,不保证原子性 |
原子性、可见性、有序性(全特性) |
| 实现原理 |
无锁,依赖内存屏障 |
加对象锁/类锁,阻塞竞争线程 |
| 性能开销 |
极轻量,几乎无开销 |
较重,竞争时会阻塞 |
| 适用范围 |
仅修饰共享变量 |
修饰实例方法、静态方法、代码块 |
| 典型场景 |
一写多读、状态标记 |
多线程写共享资源、复合操作 |
四、综合实战:线程池 + 有参回调 + 同步关键字
整合所有知识点,实现「自定义线程池执行异步任务,用volatile控制状态,synchronized保证计数器安全,有参回调处理结果」的完整场景:
import org.springframework.stereotype.Service; import javax.annotation.Resource; import java.util.concurrent.CompletableFuture; import java.util.concurrent.Executor;
@Service public class IntegratedService { @Resource(name = "customThreadPool") private Executor threadPool;
private static int taskCount = 0; private static volatile boolean isTaskEnabled = true;
private static synchronized void addTaskCount() { taskCount++; }
public CompletableFuture<String> integratedTask(String taskName) { return CompletableFuture.supplyAsync(() -> { if (!isTaskEnabled) { throw new RuntimeException("任务已禁用,无法执行"); }
addTaskCount(); System.out.println(Thread.currentThread().getName() + " 执行任务:" + taskName + ",当前总任务数:" + taskCount);
try { Thread.sleep(1000); } catch (InterruptedException e) {}
return "任务【" + taskName + "】执行完成,总任务数:" + taskCount; }, threadPool); }
public void setTaskEnabled(boolean enabled) { isTaskEnabled = enabled; } }
|
调用示例:
import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RestController; import javax.annotation.Resource; import java.util.concurrent.CompletableFuture;
@RestController public class IntegratedController { @Resource private IntegratedService integratedService;
@GetMapping("/integratedTask") public String doTask(String taskName) { CompletableFuture<String> future = integratedService.integratedTask(taskName);
future.thenAccept(result -> System.out.println("有参回调:" + result)) .exceptionally(ex -> { System.out.println("有参回调(异常):" + ex.getMessage()); return null; });
return "任务已提交,后台异步执行中..."; }
@GetMapping("/disableTask") public String disableTask() { integratedService.setTaskEnabled(false); return "任务已禁用"; } }
|
五、核心要点总结
- 线程池:核心遵循「核心线程→队列→最大线程→拒绝策略」,SpringBoot用
ThreadPoolTaskExecutor自定义,兼顾性能与稳定性;
- 异步回调:无参回调仅做完成通知,有参回调接收结果/异常(核心),基于
CompletableFuture实现,支持链式逻辑;
- volatile:轻量无锁,管「可见性+禁止重排」,适用于一写多读的状态标记,别用于多线程写;
- synchronized:重量加锁,管「原子性+可见性+有序性」,适用于多线程竞争写共享资源,保证线程安全;
- 整合使用:线程池负责并发执行,回调处理结果,同步关键字解决共享变量安全问题,三者配合实现高效、安全的并发编程。