异步处理是企业开发的‘生存之道’!Java8和Spring的异步实现,你必须搞清楚!

摘要

本文介绍Java8和Spring处理异步的两种方式。

差异性

特性 CompletableFuture.supplyAsync() @Async
依赖 Java8自带 依赖Spring
线程池管理 可显式指定线程池 可通过@Async("线程池别名")指定
异步处理 exceptionally 手动try-catch
事务支持 默认不支持 可结合@Transactional
注意事项 需手动写代码进行异步任务等待 启动类需加上@EnableAsync

示例代码

1)定义线程池

kotlin 复制代码
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(5); // 核心线程数
        executor.setMaxPoolSize(10);  // 最大线程数
        executor.setQueueCapacity(100); // 队列容量
        executor.setThreadNamePrefix("Async-"); // 线程名前缀
        executor.initialize();
        return executor;
    }
}

2)加上注解

kotlin 复制代码
@SpringBootApplication
public class AsyncUseApplication {...}

3)异步任务指定

typescript 复制代码
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Async;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.stereotype.Service;
import java.util.concurrent.CompletableFuture;

@Slf4j
@Service
public class AsyncService {

    //如果不指定线程池,CompletableFuture.supplyAsync默认使用ForkJoinPool.commonPool()
    @Autowired
    private ThreadPoolTaskExecutor threadPoolTaskExecutor;

    // 无返回值的异步方法
    @Async("taskExecutor") // 指定线程池名称
//    @Transactional(rollbackFor = Exception.class) //可结合事务
    public void asyncMethodWithoutReturn(String param) {
        try {
            log.info("异步方法块开启: " + param);
            Thread.sleep(11000); // 模拟耗时操作
        } catch (Exception e) {
            log.error("出现异常:" + e.getMessage());
        }
    }

    // 有返回值的异步方法
    @Async("taskExecutor") // 指定线程池名称
    public CompletableFuture<String> asyncMethodWithReturn(String param) {
        log.info("异步方法块开启: " + param);
        try {
            Thread.sleep(11000); // 模拟耗时操作
        } catch (Exception e) {
            log.error("出现异常:" + e.getMessage());
        }
        return CompletableFuture.completedFuture("返回结果");
    }

    // 直接使用Java 8的CompletableFuture
    public void doAsync() {
        //异步执行任务
        CompletableFuture.supplyAsync(() -> {
            try {
                //执行逻辑
                log.info("异步方法块执行");
                Thread.sleep(110000); // 模拟耗时操作
            } catch (Exception e) {
                log.error("出现异常:" + e.getMessage());
            }
            return "1";
        }, threadPoolTaskExecutor)
        //异常捕获
        .exceptionally(ex -> {
            log.error("异步任务异常:" + ex.getMessage());
            return "默认值"; // 返回默认值或处理异常
        });
        //或者处理异步结果
//        .thenAccept(result -> {
//            log.info("异步任务结果:" + result);
//        });
    }
}

4)测试任务执行

java 复制代码
import lombok.extern.slf4j.Slf4j;
import org.coffeebeans.service.AsyncService;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;

/**
 * <li>ClassName: org.org.coffeebeans.AsyncTest </li>
 * <li>Author: OakWang </li>
 */
@Slf4j
@SpringBootTest
public class AsyncTest {

    // 以下如果用sout来测试,可能会有异步顺序不对问题
    // 因为Java的System.out.println使用行缓冲:输出内容会被缓存在内存中,直到遇到换行符(\n)或程序结束时才会刷新到控制台。
    @Autowired
    private AsyncService asyncService;

    @Test
    void test1() throws InterruptedException {
       asyncService.asyncMethodWithoutReturn("测试");
       log.info("111");
       /*
          2025-08-31 16:11:55.454  INFO 19860 --- [           main] org.coffeebeans.AsyncTest                : 111
          2025-08-31 16:11:55.459  INFO 19860 --- [        Async-1] org.coffeebeans.service.AsyncService     : 异步方法块开启: 测试
        */
    }

    @Test
    void test2() throws ExecutionException, InterruptedException {
       CompletableFuture<String> future = asyncService.asyncMethodWithReturn("测试");
       log.info("111");
       log.info("异步执行返回: " + future.get());
       /*
          2025-08-31 16:10:01.082  INFO 12700 --- [           main] org.coffeebeans.AsyncTest                : 111
          2025-08-31 16:10:01.088  INFO 12700 --- [        Async-1] org.coffeebeans.service.AsyncService     : 异步方法块开启: 测试
          2025-08-31 16:10:12.094  INFO 12700 --- [           main] org.coffeebeans.AsyncTest                : 异步执行返回: 返回结果
        */
    }

    @Test
    void test3() {
       asyncService.doAsync();
       log.info("111");
       /*
          2025-08-31 16:11:14.924 INFO 17944 --- [           main] org.coffeebeans.AsyncTest                : 111
          2025-08-31 16:11:14.924 INFO 17944 --- [        Async-1] org.coffeebeans.service.AsyncService     : 异步方法块执行
        */
    }

}

总结

以上我们了解了Java8和Spring处理异步的两种方式,有各自的好,对应Spring项目示场景而定,可以混用,但需要注意线程池的管控。

关注公众号:咖啡Beans

在这里,我们专注于软件技术的交流与成长,分享开发心得与笔记,涵盖编程、AI、资讯、面试等多个领域。无论是前沿科技的探索,还是实用技巧的总结,我们都致力于为大家呈现有价值的内容。期待与你共同进步,开启技术之旅。

相关推荐
血小板要健康11 分钟前
Java基础常见面试题复习合集1
java·开发语言·经验分享·笔记·面试·学习方法
淼淼76324 分钟前
安装jdk1.8
java·开发语言
毕设源码-朱学姐44 分钟前
【开题答辩全过程】以 高校食堂餐饮管理系统的设计与实现为例,包含答辩的问题和答案
java
过期动态1 小时前
Java开发中的@EnableWebMvc注解和WebMvcConfigurer接口
java·开发语言·spring boot·spring·tomcat·maven·idea
摇滚侠1 小时前
IDEA 定义返回值快捷键
java·ide·intellij-idea
毕设源码-郭学长1 小时前
【开题答辩全过程】以 高校考勤管理系统为例,包含答辩的问题和答案
java·eclipse
A懿轩A1 小时前
【Maven 构建工具】从零到上手 Maven:安装配置 + IDEA 集成 + 第一个项目(保姆级教程)
java·maven·intellij-idea
野犬寒鸦2 小时前
从零起步学习并发编程 || 第一章:初步认识进程与线程
java·服务器·后端·学习
我爱娃哈哈2 小时前
SpringBoot + Flowable + 自定义节点:可视化工作流引擎,支持请假、报销、审批全场景
java·spring boot·后端
XiaoFan0122 小时前
将有向工作流图转为结构树的实现
java·数据结构·决策树