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 {
// 有参异步任务:返回CompletableFuture,携带结果/异常
@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
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 {
// 加volatile:保证可见性,主线程修改后子线程立即感知
private static volatile boolean isRunning = true;

public static void main(String[] args) throws InterruptedException {
// 子线程:循环执行,直到isRunning为false
new Thread(() -> {
while (isRunning) {}
System.out.println("子线程停止成功");
}).start();

// 主线程:1秒后修改状态
Thread.sleep(1000);
isRunning = false;
System.out.println("主线程已修改状态");
}
}

3.2 synchronized 关键字(重量级内置锁)

核心特性

  • 保证原子性:加锁代码同一时间仅一个线程执行,复合操作不被打断;
  • 保证可见性:释放锁时刷回主内存,加锁时读取最新值;
  • 保证有序性:加锁代码按顺序执行,禁止指令重排;
  • 缺点:加锁/解锁有开销,竞争线程会阻塞(悲观锁)。

适用场景

多线程修改共享资源、计数器、库存扣减、共享集合操作等「多线程竞争写」场景。

示例:synchronized 保证计数器安全

public class SynchronizedDemo {
private static int count = 0;

// 加synchronized:保证increment方法原子性,多线程串行执行
private static synchronized void increment() {
count++; // 复合操作:读→改→写
}

public static void main(String[] args) throws InterruptedException {
Thread[] threads = new Thread[10];
// 10个线程,每个线程执行1000次计数
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();
}

// 结果永远为10000,保证线程安全
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;

// 共享计数器:用synchronized保证线程安全
private static int taskCount = 0;
// 线程状态标记:用volatile保证可见性
private static volatile boolean isTaskEnabled = true;

// 同步方法:原子性计数
private static synchronized void addTaskCount() {
taskCount++;
}

// 整合异步任务:线程池执行 + 有参回调 + 同步关键字
public CompletableFuture<String> integratedTask(String taskName) {
return CompletableFuture.supplyAsync(() -> {
// 1. 用volatile判断状态,控制任务执行
if (!isTaskEnabled) {
throw new RuntimeException("任务已禁用,无法执行");
}

// 2. 用synchronized保证计数安全
addTaskCount();
System.out.println(Thread.currentThread().getName() + " 执行任务:" + taskName + ",当前总任务数:" + taskCount);

// 3. 模拟业务耗时
try { Thread.sleep(1000); } catch (InterruptedException e) {}

return "任务【" + taskName + "】执行完成,总任务数:" + taskCount;
}, threadPool);
}

// 控制任务状态:volatile修改后立即生效
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 "任务已禁用";
}
}

五、核心要点总结

  1. 线程池:核心遵循「核心线程→队列→最大线程→拒绝策略」,SpringBoot用ThreadPoolTaskExecutor自定义,兼顾性能与稳定性;
  2. 异步回调:无参回调仅做完成通知,有参回调接收结果/异常(核心),基于CompletableFuture实现,支持链式逻辑;
  3. volatile:轻量无锁,管「可见性+禁止重排」,适用于一写多读的状态标记,别用于多线程写;
  4. synchronized:重量加锁,管「原子性+可见性+有序性」,适用于多线程竞争写共享资源,保证线程安全;
  5. 整合使用:线程池负责并发执行,回调处理结果,同步关键字解决共享变量安全问题,三者配合实现高效、安全的并发编程。