Java 原生异步编程与Spring 异步编程 详解

发布于:2025-07-17 ⋅ 阅读:(18) ⋅ 点赞:(0)

简介

<font style="color:rgb(214, 51, 132);">Java</font> 异步编程是现代高性能应用开发的核心技术之一,它允许程序在执行耗时操作(如网络请求、文件 <font style="color:rgb(214, 51, 132);">IO</font>)时不必阻塞主线程,从而提高系统吞吐量和响应性。

异步 vs 同步

  • 同步:任务按顺序执行,后续任务需等待前任务完成。
public String syncTask() {
    // 模拟耗时操作
    Thread.sleep(1000);
    return "Result";
}
  • 异步:任务并行或在后台执行,主线程立即返回。
public CompletableFuture<String> asyncTask() {
    return CompletableFuture.supplyAsync(() -> {
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }
        return "Result";
    });
}

Java 原生异步支持

手动创建线程

最基本的异步方式是创建 <font style="color:rgb(214, 51, 132);">Thread</font> 或实现 <font style="color:rgb(214, 51, 132);">Runnable</font>

  • 缺点:管理线程池困难,资源浪费,难以复用,缺乏结果处理机制。
public class BasicAsync {
    public static void main(String[] args) {
        Thread thread = new Thread(() -> {
            try {
                Thread.sleep(1000);
                System.out.println("Task completed");
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        });
        thread.start();
        System.out.println("Main thread continues");
    }
}
使用 ExecutorService
  • 优点:提供线程池管理,复用线程,减少创建开销
  • 缺点:<font style="color:rgb(214, 51, 132);">Future.get()</font> 是阻塞的,难以链式调用
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class ThreadPoolExample {
    public static void main(String[] args) {
        ExecutorService executor = Executors.newFixedThreadPool(2);
        executor.submit(() -> {
            Thread.sleep(1000);
            System.out.println("Task 1 completed");
        });
        executor.submit(() -> {
            Thread.sleep(500);
            System.out.println("Task 2 completed");
        });
        executor.shutdown();
    }
}
常用方法:
  • <font style="color:rgb(214, 51, 132);">submit(Runnable)</font>:提交无返回值的任务。
  • <font style="color:rgb(214, 51, 132);">submit(Callable)</font>:提交有返回值的任务,返回 <font style="color:rgb(214, 51, 132);">Future</font>
  • <font style="color:rgb(214, 51, 132);">shutdown()</font>:关闭线程池,不接受新任务。
线程池类型:
  • <font style="color:rgb(214, 51, 132);">Executors.newFixedThreadPool(n)</font>:固定大小线程池。
  • <font style="color:rgb(214, 51, 132);">Executors.newCachedThreadPool()</font>:动态调整线程数。
  • <font style="color:rgb(214, 51, 132);">Executors.newSingleThreadExecutor()</font>:单线程执行。

线程池类型对比:

类型 特性 适用场景
<font style="color:rgb(214, 51, 132);">FixedThreadPool</font> 固定线程数,无界队列 负载稳定的长期任务
<font style="color:rgb(214, 51, 132);">CachedThreadPool</font> 自动扩容,60秒闲置回收 短时突发任务
<font style="color:rgb(214, 51, 132);">ScheduledThreadPool</font> 支持定时/周期性任务 心跳检测、定时报表
<font style="color:rgb(214, 51, 132);">WorkStealingPool</font> 使用 <font style="color:rgb(214, 51, 132);">ForkJoinPool</font>
,任务窃取算法
计算密集型并行任务
Future(Java 5+)
import java.util.concurrent.*;

public class FutureExample {
    public static void main(String[] args) throws Exception {
        ExecutorService executor = Executors.newFixedThreadPool(1);
        Future<String> future = executor.submit(() -> {
            Thread.sleep(1000);
            return "Task completed";
        });

        // 主线程继续
        System.out.println("Doing other work");

        // 阻塞获取结果
        String result = future.get(); // 等待任务完成
        System.out.println(result);

        executor.shutdown();
    }
}
方法
  • <font style="color:rgb(214, 51, 132);">get()</font>:阻塞获取结果。
  • <font style="color:rgb(214, 51, 132);">isDone()</font>:检查任务是否完成。
  • <font style="color:rgb(214, 51, 132);">cancel(boolean)</font>:取消任务。
缺点
  • <font style="color:rgb(214, 51, 132);">get()</font> 是阻塞的,不利于非阻塞编程。
  • 难以组合多个异步任务。
CompletableFuture(Java 8+)

支持链式调用,真正现代化异步编程方式。

import java.util.concurrent.CompletableFuture;

public class CompletableFutureExample {
    public static void main(String[] args) {
        CompletableFuture.supplyAsync(() -> {
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
            return "Task result";
        })
        .thenApply(result -> result.toUpperCase()) // 转换结果
        .thenAccept(result -> System.out.println(result)) // 消费结果
        .exceptionally(throwable -> {
            System.err.println("Error: " + throwable.getMessage());
            return null;
        });

        System.out.println("Main thread continues");
    }
}
虚拟线程(Java 21+,Project Loom)

虚拟线程是 <font style="color:rgb(214, 51, 132);">Java 21</font> 引入的轻量级线程,适合高并发 I/O 密集型任务。

public class VirtualThreadExample {
    public static void main(String[] args) {
        try (var executor = Executors.newVirtualThreadPerTaskExecutor()) {
            executor.submit(() -> {
                try {
                    Thread.sleep(1000);
                    System.out.println("Task completed in virtual thread");
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            });
        }
        System.out.println("Main thread continues");
    }
}

优势

  • 轻量级,创建开销极低(相比传统线程)。
  • 适合 I/O 密集型任务(如 HTTP 请求、数据库查询)。

注意

  • 不适合 <font style="color:rgb(214, 51, 132);">CPU</font> 密集型任务(可能导致线程饥饿)。
  • <font style="color:rgb(214, 51, 132);">Spring Boot 3.2+</font> 支持虚拟线程(需配置)。
阻塞 vs 非阻塞
类型 是否阻塞 获取结果方式
<font style="color:rgb(214, 51, 132);">Future<T></font> ✅ 是 <font style="color:rgb(214, 51, 132);">future.get()</font>
(阻塞)
<font style="color:rgb(214, 51, 132);">CompletableFuture<T></font> ✅(get) ❌(then) 支持非阻塞链式处理
<font style="color:rgb(214, 51, 132);">@Async + Future/CompletableFuture</font> <font style="color:rgb(214, 51, 132);">get()</font>
或回调
<font style="color:rgb(214, 51, 132);">WebFlux</font> ❌ 完全非阻塞 响应式 <font style="color:rgb(214, 51, 132);">Mono</font>
/ <font style="color:rgb(214, 51, 132);">Flux</font>
<font style="color:rgb(214, 51, 132);">Future<T></font> vs <font style="color:rgb(214, 51, 132);">CompletableFuture<T></font>:核心对比
功能 **<font style="color:rgb(214, 51, 132);">Future<T></font>** **<font style="color:rgb(214, 51, 132);">CompletableFuture<T></font>**
Java 版本 Java 5+ Java 8+
是否可组合 ❌ 不支持 ✅ 支持链式组合、并行执行
支持异步回调 ❌ 无 ✅ 有 <font style="color:rgb(214, 51, 132);">.thenApply()</font>
<font style="color:rgb(214, 51, 132);">.thenAccept()</font>
支持异常处理 ❌ 无 ✅ 有 <font style="color:rgb(214, 51, 132);">.exceptionally()</font>
可取消 ✅ 支持 <font style="color:rgb(214, 51, 132);">cancel()</font> ✅ 也支持
阻塞获取 <font style="color:rgb(214, 51, 132);">get()</font>
阻塞
<font style="color:rgb(214, 51, 132);">get()</font>
阻塞(也可非阻塞)
使用场景 简单线程任务 多异步任务组合、复杂控制流

Spring 异步编程(基于 @Async)

配置类或启动类启用异步支持
@SpringBootApplication
@EnableAsync
public class Application {
    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }
}
@Configuration
@EnableAsync
public class AsyncConfig {
}
无返回值用法
// 无返回值的异步方法
@Async
public void sendEmail(String to) {
    System.out.println("异步发送邮件给: " + to);
    try { Thread.sleep(2000); } catch (InterruptedException e) {}
    System.out.println("邮件发送完成");
}
使用 <font style="color:rgb(214, 51, 132);">Future<T></font>

创建异步方法

@Service
public class AsyncService {
    @Async
    public Future<String> processTask() {
        // 模拟耗时操作
        return new AsyncResult<>("Task completed");
    }
}

调用并获取结果:

@Autowired
private AsyncService asyncService;

public void executeTask() throws Exception {
    Future<String> future = asyncService.processTask();
    String result = future.get(); // 阻塞等待结果
}
使用 <font style="color:rgb(214, 51, 132);">CompletableFuture<T></font>

创建异步方法

@Async
public CompletableFuture<String> asyncMethod() {
    return CompletableFuture.completedFuture("Async Result");
}

调用方式:

CompletableFuture<String> result = asyncService.asyncMethod();
// 非阻塞,可以做其他事
String value = result.get(); // 阻塞获取
线程池配置
使用自定义配置类
@Configuration
public class AsyncConfig {

    @Bean("taskExecutor")
    public Executor taskExecutor() {
        ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
        executor.setCorePoolSize(5);      // 核心线程数
        executor.setMaxPoolSize(20);      // 最大线程数
        executor.setQueueCapacity(100);   // 队列容量
        executor.setKeepAliveSeconds(30); // 空闲线程存活时间
        executor.setThreadNamePrefix("async-task-");
        executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
        executor.initialize();
        return executor;
    }
}

// 指定线程池
@Async("taskExecutor")
public Future<String> customPoolTask() { ... }
使用配置文件
# application.yml
spring:
  task:
    execution:
      pool:
        core-size: 5
        max-size: 20
        queue-capacity: 100
        thread-name-prefix: async-
      shutdown:
        await-termination: true
        terminate-on-timeout: true
Spring WebFlux 示例
@Service
public class UserService {
    public Mono<String> getUser() {
        return Mono.just("用户信息").delayElement(Duration.ofSeconds(2));
    }

    public Flux<String> getAllUsers() {
        return Flux.just("用户1", "用户2", "用户3").delayElements(Duration.ofSeconds(1));
    }
}
@RestController
@RequestMapping("/users")
public class UserController {

    @Autowired
    private UserService userService;

    @GetMapping("/one")
    public Mono<String> getUser() {
        return userService.getUser();
    }

    @GetMapping("/all")
    public Flux<String> getAllUsers() {
        return userService.getAllUsers();
    }
}

调用时非阻塞行为体现

  • <font style="color:rgb(214, 51, 132);">Mono<String></font> 表示未来异步返回一个值;
  • <font style="color:rgb(214, 51, 132);">Flux<String></font> 表示异步返回多个值;
  • 请求立即返回 <font style="color:rgb(214, 51, 132);">Publisher</font>,只有订阅时才开始执行(懒执行、非阻塞);
  • 它不占用线程,不会“卡死线程”等待值返回。
SpringBoot 集成示例
  • 标记 <font style="color:rgb(214, 51, 132);">@Async</font> 注解:

<font style="color:rgb(214, 51, 132);">@Async</font> 标记方法为异步执行,<font style="color:rgb(214, 51, 132);">Spring</font> 在线程池中运行该方法。

import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;

@Service
public class AsyncService {
    @Async
    public CompletableFuture<String> doAsyncTask() {
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }
        return CompletableFuture.completedFuture("Task completed");
    }
}
  • 启用异步

在主类或配置类上添加 <font style="color:rgb(214, 51, 132);">@EnableAsync</font>

@SpringBootApplication
@EnableAsync
public class Application {
    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }
}
  • 控制器调用异步方法
@RestController
public class AsyncController {
    @Autowired
    private AsyncService asyncService;

    @GetMapping("/async")
    public String triggerAsync() {
        asyncService.doAsyncTask().thenAccept(result -> System.out.println(result));
        return "Task triggered";
    }
}
  • 自定义线程池

<font style="color:rgb(214, 51, 132);">Spring</font> 默认使用 <font style="color:rgb(214, 51, 132);">SimpleAsyncTaskExecutor</font>,不适合生产环境。推荐配置自定义线程池。

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;

@Configuration
public class AsyncConfig {
    @Bean(name = "taskExecutor")
    public ThreadPoolTaskExecutor taskExecutor() {
        ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
        executor.setCorePoolSize(2);
        executor.setMaxPoolSize(10);
        executor.setQueueCapacity(25);
        executor.setThreadNamePrefix("AsyncThread-");
        executor.initialize();
        return executor;
    }
}
  • 指定线程池:
@Async("taskExecutor")
public CompletableFuture<String> doAsyncTask() {
    // 异步逻辑
}
  • <font style="color:rgb(214, 51, 132);">@Async</font> 方法定义全局异常处理器
@Component
public class AsyncExceptionHandler implements AsyncUncaughtExceptionHandler {
    @Override
    public void handleUncaughtException(Throwable ex, Method method, Object... params) {
        System.err.println("Async error: " + ex.getMessage());
    }
}
  • <font style="color:rgb(214, 51, 132);">Spring Boot</font> 测试:
@SpringBootTest
public class AsyncServiceTest {
    @Autowired
    private AsyncService asyncService;

    @Test
    void testAsync() throws Exception {
        CompletableFuture<String> future = asyncService.doAsyncTask();
        assertEquals("Task completed", future.get(2, TimeUnit.SECONDS));
    }
}
并行调用多个服务示例

并行调用 <font style="color:rgb(214, 51, 132);">getUser</font><font style="color:rgb(214, 51, 132);">getProfile</font>,总耗时接近较慢的任务(~1s)。

@Service
public class UserService {
    @Async
    public CompletableFuture<User> getUser(Long id) {
        return CompletableFuture.supplyAsync(() -> {
            // 模拟远程调用
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
            return new User(id, "User" + id);
        });
    }

    @Async
    public CompletableFuture<Profile> getProfile(Long id) {
        return CompletableFuture.supplyAsync(() -> {
            try {
                Thread.sleep(500);
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
            return new Profile(id, "Profile" + id);
        });
    }
}

@RestController
public class UserController {
    @Autowired
    private UserService userService;

    @GetMapping("/user/{id}")
    public CompletableFuture<UserProfile> getUserProfile(@PathVariable Long id) {
        return userService.getUser(id)
            .thenCombine(userService.getProfile(id),
                (user, profile) -> new UserProfile(user, profile));
    }
}
异步批量处理示例

并行处理 10 个任务,显著减少总耗时。

@Service
public class BatchService {
    @Async
    public CompletableFuture<Void> processItem(int item) {
        return CompletableFuture.runAsync(() -> {
            try {
                Thread.sleep(100);
                System.out.println("Processed item: " + item);
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
        });
    }
}

@RestController
public class BatchController {
    @Autowired
    private BatchService batchService;

    @PostMapping("/batch")
    public CompletableFuture<Void> processBatch() {
        List<CompletableFuture<Void>> futures = new ArrayList<>();
        for (int i = 1; i <= 10; i++) {
            futures.add(batchService.processItem(i));
        }
        return CompletableFuture.allOf(futures.toArray(new CompletableFuture[0]));
    }
}
响应式 WebFlux 示例
@Service
public class ReactiveService {
    public Mono<String> fetchData() {
        return Mono.just("Data")
                   .delayElement(Duration.ofSeconds(1));
    }
}

@RestController
public class ReactiveController {
    @Autowired
    private ReactiveService reactiveService;

    @GetMapping("/data")
    public Mono<String> getData() {
        return reactiveService.fetchData();
    }
}
Spring Data JPA 集成示例

<font style="color:rgb(214, 51, 132);">JPA</font> 默认阻塞操作,可通过 <font style="color:rgb(214, 51, 132);">@Async</font> 包装异步调用。

@Repository
public interface UserRepository extends JpaRepository<User, Long> {}

@Service
public class UserService {
    @Autowired
    private UserRepository userRepository;

    @Async
    public CompletableFuture<User> findUser(Long id) {
        return CompletableFuture.supplyAsync(() -> userRepository.findById(id).orElse(null));
    }
}
MyBatis Plus 集成示例

<font style="color:rgb(214, 51, 132);">MyBatis Plus</font> 默认阻塞,可通过 <font style="color:rgb(214, 51, 132);">@Async</font> 或线程池异步化。

@Mapper
public interface UserMapper extends BaseMapper<User> {}

@Service
public class UserService {
    @Autowired
    private UserMapper userMapper;

    @Async
    public CompletableFuture<User> getUser(Long id) {
        return CompletableFuture.supplyAsync(() -> userMapper.selectById(id));
    }
}
注意事项
  • <font style="color:rgb(214, 51, 132);">@Async</font> 方法必须是 <font style="color:rgb(214, 51, 132);">public</font> 的。
  • 不能在同一类内调用 <font style="color:rgb(214, 51, 132);">@Async</font> 方法(因 <font style="color:rgb(214, 51, 132);">Spring AOP</font> 代理机制)。
  • 默认线程池由 <font style="color:rgb(214, 51, 132);">Spring</font> 提供,可自定义。

CompletableFuture 所有核心 API

  • <font style="color:rgb(214, 51, 132);">supplyAsync()</font>:异步执行任务,返回值
  • <font style="color:rgb(214, 51, 132);">runAsync()</font>:异步执行任务,无返回值
  • <font style="color:rgb(214, 51, 132);">thenApply()</font>:接收前面任务结果并返回新结果
  • <font style="color:rgb(214, 51, 132);">thenAccept()</font>:接收结果但无返回
  • <font style="color:rgb(214, 51, 132);">thenRun()</font>:不接收结果也不返回,仅执行
  • <font style="color:rgb(214, 51, 132);">thenCompose()</font>:嵌套异步任务
  • <font style="color:rgb(214, 51, 132);">thenCombine()</font>:两个任务都完成后,合并结果
  • <font style="color:rgb(214, 51, 132);">allOf()</font>:等多个任务全部完成
  • <font style="color:rgb(214, 51, 132);">anyOf()</font>:任一任务完成即继续
  • <font style="color:rgb(214, 51, 132);">exceptionally()</font>:捕获异常并处理
  • <font style="color:rgb(214, 51, 132);">whenComplete()</font>:无论成功失败都执行
  • <font style="color:rgb(214, 51, 132);">handle()</font>:可处理正常或异常结果

<font style="color:rgb(214, 51, 132);">CompletableFuture<T></font> 用法详解

创建异步任务
<font style="color:rgb(214, 51, 132);">supplyAsync</font>:基本异步任务执行
CompletableFuture<String> cf = CompletableFuture.supplyAsync(() -> "Result");
<font style="color:rgb(214, 51, 132);">runAsync</font>:异步执行任务,无返回值
CompletableFuture<Void> cf = CompletableFuture.runAsync(() -> System.out.println("Async run"));
任务转换
<font style="color:rgb(214, 51, 132);">thenApply(Function)</font>:转换结果,对结果加工
CompletableFuture<String> future = CompletableFuture
    .supplyAsync(() -> "data")
    .thenApply(data -> data.toUpperCase());

System.out.println(future.get()); // DATA
<font style="color:rgb(214, 51, 132);">thenCompose(Function)</font>:扁平化链式异步
CompletableFuture<String> composed = CompletableFuture
    .supplyAsync(() -> "A")
    .thenCompose(a -> CompletableFuture.supplyAsync(() -> a + "B"));

composed.thenAccept(System.out::println); // 输出 AB
<font style="color:rgb(214, 51, 132);">thenCombine(CompletionStage, BiFunction)</font>:两个任务完成后合并结果
CompletableFuture<String> cf1 = CompletableFuture.supplyAsync(() -> "Hello");
CompletableFuture<String> cf2 = CompletableFuture.supplyAsync(() -> "World");

cf1.thenCombine(cf2, (a, b) -> a + " " + b).thenAccept(System.out::println);
CompletableFuture<String> f1 = CompletableFuture.supplyAsync(() -> "A");
CompletableFuture<String> f2 = CompletableFuture.supplyAsync(() -> "B");

CompletableFuture<String> result = f1.thenCombine(f2, (a, b) -> a + b);
System.out.println(result.get()); // AB
消费结果
<font style="color:rgb(214, 51, 132);">thenAccept(Consumer)</font>:消费结果
CompletableFuture
    .supplyAsync(() -> "Result")
    .thenAccept(result -> System.out.println("Received: " + result));
<font style="color:rgb(214, 51, 132);">thenRun(Runnable)</font>:继续执行下一个任务,无需前面结果
CompletableFuture
    .supplyAsync(() -> "X")
    .thenRun(() -> System.out.println("Next step executed"));
异常处理
<font style="color:rgb(214, 51, 132);">exceptionally(Function<Throwable, T>)</font>:异常处理
CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> {
    if (true) throw new RuntimeException("Oops!");
    return "ok";
}).exceptionally(ex -> "Fallback: " + ex.getMessage());

System.out.println(future.get());
<font style="color:rgb(214, 51, 132);">handle(BiFunction<T, Throwable, R>)</font>:同时处理正常与异常结果
CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> {
    throw new RuntimeException("Error!");
}).handle((result, ex) -> {
    if (ex != null) return "Handled: " + ex.getMessage();
    return result;
});

System.out.println(future.get());
<font style="color:rgb(214, 51, 132);">whenComplete(BiConsumer<T, Throwable>)</font>:类似 finally
  • <font style="color:rgb(214, 51, 132);">CompletableFuture</font> 执行完毕后执行一个回调,无论是成功还是异常。
  • 不会改变原来的结果或异常,仅用于处理副作用(如日志)。
CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> "Final Result")
    .whenComplete((result, ex) -> {
        System.out.println("Completed with: " + result);
    });
CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> {
    if (true) throw new RuntimeException("出错了");
    return "成功";
}).whenComplete((result, exception) -> {
    if (exception != null) {
        System.out.println("发生异常:" + exception.getMessage());
    } else {
        System.out.println("执行结果:" + result);
    }
});
并发组合
allOf / anyOf:组合任务
CompletableFuture<Void> all = CompletableFuture.allOf(task1, task2);
CompletableFuture<Object> any = CompletableFuture.anyOf(task1, task2);
allOf(…):等待全部任务完成

需要单独从每个任务中再 <font style="color:rgb(214, 51, 132);">.get()</font> 拿到结果

CompletableFuture<String> f1 = CompletableFuture.supplyAsync(() -> "A");
CompletableFuture<String> f2 = CompletableFuture.supplyAsync(() -> "B");

CompletableFuture<Void> all = CompletableFuture.allOf(f1, f2);
all.thenRun(() -> System.out.println("All done")).get();
CompletableFuture<String> userFuture = CompletableFuture.supplyAsync(() -> fetchUser());
CompletableFuture<String> orderFuture = CompletableFuture.supplyAsync(() -> fetchOrder());

// 两个任务都完成后执行
CompletableFuture<Void> bothDone = CompletableFuture.allOf(userFuture, orderFuture);

bothDone.thenRun(() -> {
    try {
        String user = userFuture.get();
        String order = orderFuture.get();
        System.out.println("用户: " + user + ", 订单: " + order);
    } catch (Exception e) {
        e.printStackTrace();
    }
});
anyOf(…):任一完成即触发
CompletableFuture<String> f1 = CompletableFuture.supplyAsync(() -> {
    try { Thread.sleep(1000); } catch (InterruptedException e) {}
    return "fast";
});
CompletableFuture<String> f2 = CompletableFuture.supplyAsync(() -> "slow");

CompletableFuture<Object> any = CompletableFuture.anyOf(f1, f2);
System.out.println(any.get()); // 输出最快那个
超时控制
<font style="color:rgb(214, 51, 132);">orTimeout(long timeout, TimeUnit unit)</font>:超时异常

如果在指定时间内没有完成,就抛出 <font style="color:rgb(214, 51, 132);">TimeoutException</font> 异常。

CompletableFuture<String> f = CompletableFuture.supplyAsync(() -> {
    try { Thread.sleep(2000); } catch (Exception e) {}
    return "late result";
}).orTimeout(1, TimeUnit.SECONDS);

try {
    System.out.println(f.get());
} catch (Exception e) {
    System.out.println("Timeout: " + e.getMessage());
}
CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> {
    try {
        Thread.sleep(3000);
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
    return "执行完成";
}).orTimeout(2, TimeUnit.SECONDS)
  .exceptionally(ex -> "捕获到异常:" + ex.getClass().getSimpleName());

System.out.println("结果:" + future.join()); // 打印“捕获到异常:TimeoutException”
<font style="color:rgb(214, 51, 132);">completeOnTimeout(T value, long timeout, TimeUnit unit)</font>:超时默认值

如果在指定时间内没有完成,则返回一个默认值,并完成该任务。

CompletableFuture<String> f = CompletableFuture.supplyAsync(() -> {
    try { Thread.sleep(2000); } catch (Exception e) {}
    return "slow";
}).completeOnTimeout("timeout default", 1, TimeUnit.SECONDS);

System.out.println(f.get()); // timeout default
CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> {
    try {
        Thread.sleep(3000); // 模拟耗时任务
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
    return "正常返回结果";
}).completeOnTimeout("超时默认值", 2, TimeUnit.SECONDS);

System.out.println("最终结果:" + future.join()); // 会打印“超时默认值”
自定义线程池
ExecutorService pool = Executors.newFixedThreadPool(2);

CompletableFuture<String> f = CompletableFuture.supplyAsync(() -> "pooled", pool);
System.out.println(f.get());
pool.shutdown();
异步任务 + 消费结果
CompletableFuture<Void> future = CompletableFuture
    .supplyAsync(() -> "hello")
    .thenAccept(result -> System.out.println("结果是:" + result));
异步任务 + 转换结果(链式调用)
CompletableFuture<String> future = CompletableFuture
    .supplyAsync(() -> "5")
    .thenApply(Integer::parseInt)
    .thenApply(num -> num * 2)
    .thenApply(Object::toString);
异常处理
CompletableFuture<String> future = CompletableFuture
    .supplyAsync(() -> {
        if (true) throw new RuntimeException("出错了!");
        return "success";
    })
    .exceptionally(ex -> {
        System.out.println("异常: " + ex.getMessage());
        return "默认值";
    });
多任务并发组合(allOf / anyOf)
CompletableFuture<String> f1 = CompletableFuture.supplyAsync(() -> "A");
CompletableFuture<String> f2 = CompletableFuture.supplyAsync(() -> "B");

// 等待全部完成
CompletableFuture<Void> all = CompletableFuture.allOf(f1, f2);
all.join();

System.out.println("结果:" + f1.join() + ", " + f2.join());
合并两个任务结果
CompletableFuture<Integer> f1 = CompletableFuture.supplyAsync(() -> 100);
CompletableFuture<Integer> f2 = CompletableFuture.supplyAsync(() -> 200);

CompletableFuture<Integer> result = f1.thenCombine(f2, Integer::sum);
System.out.println(result.get()); // 输出 300
自定义线程池
ExecutorService pool = Executors.newFixedThreadPool(4);

CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> {
    return "线程池中的任务";
}, pool);

System.out.println(future.get());
pool.shutdown();
链式异步处理
CompletableFuture.supplyAsync(() -> "Step 1")
    .thenApply(s -> s + " -> Step 2")
    .thenCompose(s -> CompletableFuture.supplyAsync(() -> s + " -> Step 3"))
    .thenAccept(System.out::println)
    .exceptionally(ex -> {
        ex.printStackTrace();
        return null;
    });
订单处理示例
public class OrderSystem {
    @Async("dbExecutor")
    public CompletableFuture<Order> saveOrder(Order order) {
        // 数据库写入操作
        return CompletableFuture.completedFuture(order);
    }

    @Async("httpExecutor")
    public CompletableFuture<String> notifyLogistics(Order order) {
        // 调用物流API
        return CompletableFuture.completedFuture("SUCCESS");
    }

    public void processOrder(Order order) {
        CompletableFuture<Order> saveFuture = saveOrder(order);
        saveFuture.thenCompose(savedOrder -> 
            notifyLogistics(savedOrder)
        ).exceptionally(ex -> {
            log.error("物流通知失败", ex);
            return "FALLBACK";
        });
    }
}
总结图谱
CompletableFuture
├─ 创建任务
│  ├─ runAsync() -> 无返回值
│  └─ supplyAsync() -> 有返回值
├─ 处理结果
│  ├─ thenApply() -> 转换
│  ├─ thenAccept() -> 消费
│  ├─ thenRun() -> 执行新任务
│  ├─ thenCombine() -> 合并结果
│  └─ thenCompose() -> 链式调用
├─ 异常处理
│  ├─ exceptionally()
│  ├─ handle()
│  └─ whenComplete()
├─ 组合任务
│  ├─ allOf()
│  └─ anyOf()
└─ 超时控制
   ├─ orTimeout()
   └─ completeOnTimeout()

什么场景适合用 Java 异步(@Async / CompletableFuture)?

场景 是否适合异步?
调用多个远程服务并行 ✅ 很适合
复杂 CPU 运算耗时任务 ✅ 可以放到异步线程池
简单业务逻辑、数据库操作 ❌ 不建议,同步更可控
非主流程的日志、打点操作 ✅ 合适异步处理

Java 和 .NET 异步处理对比

并行调用两个服务,提高响应速度

Spring Boot 示例(@Async + CompletableFuture)

项目结构

└── src
    └── main
        ├── java
        │   ├── demo
        │   │   ├── controller
        │   │   │   └── AggregateController.java
        │   │   ├── service
        │   │   │   ├── RemoteService.java
        │   │   │   └── RemoteServiceImpl.java
        │   │   └── DemoApplication.java

RemoteService.java

public interface RemoteService {
    @Async
    CompletableFuture<String> getUserInfo();

    @Async
    CompletableFuture<String> getAccountInfo();
}

RemoteServiceImpl.java

@Service
public class RemoteServiceImpl implements RemoteService {

    @Override
    public CompletableFuture<String> getUserInfo() {
        try {
            Thread.sleep(2000); // 模拟耗时
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }
        return CompletableFuture.completedFuture("UserInfo");
    }

    @Override
    public CompletableFuture<String> getAccountInfo() {
        try {
            Thread.sleep(3000); // 模拟耗时
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }
        return CompletableFuture.completedFuture("AccountInfo");
    }
}

AggregateController.java

@RestController
@RequestMapping("/api")
public class AggregateController {

    @Autowired
    private RemoteService remoteService;

    @GetMapping("/aggregate")
    public ResponseEntity<String> aggregate() throws Exception {
        CompletableFuture<String> userFuture = remoteService.getUserInfo();
        CompletableFuture<String> accountFuture = remoteService.getAccountInfo();

        // 等待所有完成
        CompletableFuture.allOf(userFuture, accountFuture).join();

        // 获取结果
        String result = userFuture.get() + " + " + accountFuture.get();
        return ResponseEntity.ok(result);
    }
}

DemoApplication.java

@SpringBootApplication
@EnableAsync
public class DemoApplication {
    public static void main(String[] args) {
        SpringApplication.run(DemoApplication.class, args);
    }
}
.NET 示例(async/await)

项目结构

└── Controllers
    └── AggregateController.cs
└── Services
    └── IRemoteService.cs
    └── RemoteService.cs

IRemoteService.cs

public interface IRemoteService {
    Task<string> GetUserInfoAsync();
    Task<string> GetAccountInfoAsync();
}

RemoteService.cs

public class RemoteService : IRemoteService {
    public async Task<string> GetUserInfoAsync() {
        await Task.Delay(2000); // 模拟耗时
        return "UserInfo";
    }

    public async Task<string> GetAccountInfoAsync() {
        await Task.Delay(3000); // 模拟耗时
        return "AccountInfo";
    }
}

AggregateController.cs

[ApiController]
[Route("api/[controller]")]
public class AggregateController : ControllerBase {
    private readonly IRemoteService _remoteService;

    public AggregateController(IRemoteService remoteService) {
        _remoteService = remoteService;
    }

    [HttpGet("aggregate")]
    public async Task<IActionResult> Aggregate() {
        var userTask = _remoteService.GetUserInfoAsync();
        var accountTask = _remoteService.GetAccountInfoAsync();

        await Task.WhenAll(userTask, accountTask);

        var result = $"{userTask.Result} + {accountTask.Result}";
        return Ok(result);
    }
}
Java vs .NET 异步用法对比总结
方面 Java(Spring Boot) .NET Core(ASP.NET)
异步声明方式 <font style="color:rgb(214, 51, 132);">@Async</font>
+ <font style="color:rgb(214, 51, 132);">CompletableFuture</font>
<font style="color:rgb(214, 51, 132);">async/await</font>
返回值类型 <font style="color:rgb(214, 51, 132);">CompletableFuture<T></font> <font style="color:rgb(214, 51, 132);">Task<T></font>
等待多个任务 <font style="color:rgb(214, 51, 132);">CompletableFuture.allOf()</font> <font style="color:rgb(214, 51, 132);">Task.WhenAll()</font>
是否阻塞 <font style="color:rgb(214, 51, 132);">.get()</font>
会阻塞,链式不阻塞
<font style="color:rgb(214, 51, 132);">await</font>
非阻塞
简洁性 稍复杂(需要注解和线程池配置) 极简、天然异步支持

网站公告

今日签到

点亮在社区的每一天
去签到