CompletableFuture 和@Async 配置自定义线程池

本文介绍了Spring Boot中如何配置自定义线程池,包括使用ThreadPoolTaskExecutor并设置各项参数,以及如何处理线程池的拒绝策略。通过CompletableFuture示例展示了异步任务的执行,并给出了实际运行结果。

介绍,配置自定义线程池,可以处理线程异常情况 ,不配置,都走自带的线程池,不好。下面是自定义线程池的方法,可以把@Bean放到配置类中。在丰富一下线程池的几个参数,建好对应的表存入异常的执行任务。

【1】TaskExecutor

Spring异步线程池的接口类,其实质是java.util.concurrent.Executor。

Spring 已经实现的异常线程池:

① SimpleAsyncTaskExecutor:不是真的线程池,这个类不重用线程,每次调用都会创建一个新的线程。

② SyncTaskExecutor:这个类没有实现异步调用,只是一个同步操作,只适用于不需要多线程的地方。

③ ConcurrentTaskExecutor:Executor的适配类,不推荐使用。如果ThreadPoolTaskExecutor不满足要求时,才用考虑使用这个类 。

④ SimpleThreadPoolTaskExecutor:是Quartz的SimpleThreadPool的类。线程池同时被quartz和非quartz使用,才需要使用此类。

⑤ ThreadPoolTaskExecutor :最常使用,推荐。 其实质是对java.util.concurrent.ThreadPoolExecutor的包装。
 

代码:

启动开启异步:

@SpringBootApplication
//开启才可以
@EnableAsync
public class DemoApplication {

    public static void main(String[] args) {
        SpringApplication.run(DemoApplication.class, args);
    }

}
package com.example.nacosdemo;

import com.example.nacosdemo.service.AsyncService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.concurrent.*;

@RestController
public class TestController {

    //============================================CompletableFuture=====配置自定义的线程池================================
    @Qualifier("selfThreadPoolExecutor")

    @Autowired
    private ThreadPoolTaskExecutor threadPoolTaskExecutor;
    @Autowired
    private AsyncService asyncService;

    @RequestMapping("/getThreadPool")
    public String getThreadPool() throws ExecutionException, InterruptedException {
        System.out.println("getsgg..."+Thread.currentThread().getName());
        //1.无返回值的异步任务 runAsync()
        Executor service;
        CompletableFuture<Void> voidCompletableFuture = CompletableFuture.runAsync(() -> {
            System.out.println("线程号为***" + Thread.currentThread().getId()+"线程名称..."+Thread.currentThread().getName());
            int i = 5;
            System.out.println("---------" + i);
        }, threadPoolTaskExecutor);
        System.out.println("结果是+=="+ voidCompletableFuture.get());
        return "ok";
    }

//============================================@Async=====配置自定义的线程池================================
    /**
     * 测试异步执行线程池
     * @return
     * @throws ExecutionException
     * @throws InterruptedException
     */
    @RequestMapping("/getOk")
    public String getDe() throws ExecutionException, InterruptedException {
        System.out.println("主线程名称..."+Thread.currentThread().getName());
        Future<String> future = asyncService.asyncInvokeReturnFuture(5);
        System.out.println("结果是+=="+ future.get());
        return "ok";
    }




}
package com.example.nacosdemo.config;

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

import java.util.concurrent.RejectedExecutionHandler;
import java.util.concurrent.ThreadPoolExecutor;

@Configuration
public class PoolConfig {
    @Bean
    public ThreadPoolTaskExecutor selfThreadPoolExecutor() {
        ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
        //设置线程名称
        executor.setThreadNamePrefix("completableFuture--pool");
        //设置最大线程数
        executor.setMaxPoolSize(50);
        //设置核心线程数
        executor.setCorePoolSize(10);
        //设置线程空闲时间,默认60
        executor.setKeepAliveSeconds(60);
        //设置队列容量
        executor.setQueueCapacity(1000);

        // 设置拒绝策略
        executor.setRejectedExecutionHandler(new RejectedExecutionHandler() {
            @Override
            public void rejectedExecution(Runnable r, ThreadPoolExecutor executor) {
                // .....任务过多时,存入数据库,定时执行,还是...
            }
        });
        // 使用预定义的异常处理类
        // executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());

        return executor;
    }

    /**
     * 自定义异步线程池
     * @return
     */
    @Bean
    public AsyncTaskExecutor taskExecutor() {
        ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
        //设置线程名称
        executor.setThreadNamePrefix("Anno-Executor");
        //设置最大线程数
        executor.setMaxPoolSize(50);
        //设置核心线程数
        executor.setCorePoolSize(10);
        //设置线程空闲时间,默认60
        executor.setKeepAliveSeconds(60);
        //设置队列容量
        executor.setQueueCapacity(1000);

        // 设置拒绝策略
        executor.setRejectedExecutionHandler(new RejectedExecutionHandler() {
            @Override
            public void rejectedExecution(Runnable r, ThreadPoolExecutor executor) {
                // .....任务过多时,存入数据库,定时执行,还是...
            }
        });
        // 使用预定义的异常处理类
        // executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());

        return executor;
    }
}

package com.example.nacosdemo.service;

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

import java.util.concurrent.Future;
@Service
public class AsyncService {
    /**
     * 异步调用返回Future
     *
     * @param i
     * @return
     */
    @Async
    public Future<String> asyncInvokeReturnFuture(int i) {
        System.out.println("进入asyncInvokeReturnFuture...线程名称=="+Thread.currentThread().getName());
        Future<String> future;
        try {
            Thread.sleep(3000);
            System.out.println("3S后asyncInvokeReturnFuture数据开始处理中。。");
            future = new AsyncResult<String>("success:" + i);
        } catch (InterruptedException e) {
            future = new AsyncResult<String>("error");
        }
        return future;
    }

}

2. 执行结果:

completableFuture的执行结果

getsgg...http-nio-8080-exec-3
线程号为***36线程名称...completableFuture--pool1
---------5
结果是+==null
getsgg...http-nio-8080-exec-4
线程号为***38线程名称...completableFuture--pool2
---------5
结果是+==null
getsgg...http-nio-8080-exec-5
线程号为***40线程名称...completableFuture--pool3
---------5
结果是+==null
getsgg...http-nio-8080-exec-6
线程号为***51线程名称...completableFuture--pool4
---------5
结果是+==null
getsgg...http-nio-8080-exec-7
线程号为***53线程名称...completableFuture--pool5
---------5
结果是+==null
主线程名称...http-nio-8080-exec-1
进入asyncInvokeReturnFuture...线程名称==Anno-Executor1
主线程名称...http-nio-8080-exec-2
进入asyncInvokeReturnFuture...线程名称==Anno-Executor2
主线程名称...http-nio-8080-exec-3
进入asyncInvokeReturnFuture...线程名称==Anno-Executor3
主线程名称...http-nio-8080-exec-4
进入asyncInvokeReturnFuture...线程名称==Anno-Executor4
3S后asyncInvokeReturnFuture数据开始处理中。。
结果是+==success:5
3S后asyncInvokeReturnFuture数据开始处理中。。
结果是+==success:5
3S后asyncInvokeReturnFuture数据开始处理中。。
结果是+==success:5
3S后asyncInvokeReturnFuture数据开始处理中。。
结果是+==success:5

关于    CompletableFuture    使用参考网址:



多线程、线程池的创建方式,为什么阿里推荐自定义线程池?_知识分子_的博客-优快云博客_completablefuture 线程池

SpringBoot - @Async异步任务与线程池_小小默:进无止境-优快云博客 

<think>嗯,用户的问题是关于如何在Spring中使用@Async注解时指定自定义线程池配置方法。我需要先回想一下相关的知识,然后结合提供的引用内容来组织答案。 首先,用户可能已经知道@Async的基本用法,但需要具体的配置步骤。根据引用内容,Spring自定义线程池通常涉及到配置ThreadPoolTaskExecutor或者实现AsyncConfigurer接口。例如,引用[1]提到了配置核心线程数、最大线程数等参数。引用[2][3]则提到了在方法上使用@Async并指定线程池的名称,以及启动类需要@EnableAsync注解。 接下来,我需要确定回答的结构。应该分步骤说明,包括配置线程池、启用异步支持、在代码中使用自定义线程池,以及可能的其他注意事项。引用[4]提到不要使用默认的SimpleAsyncTaskExecutor,所以需要强调自定义的重要性。 还需要注意是否需要代码示例。引用[2][3]提供了代码片段,比如配置类中的@Bean方法,以及在方法上使用@Async("myExecutor")。这些代码示例对用户会有帮助,应该包含在回答中。 另外,用户可能想知道如何在不同场景下使用自定义线程池,比如在CompletableFuture中,如引用[2]提到的。这部分可以作为扩展应用场景来补充。 最后,检查是否有遗漏的要点,比如线程池参数配置的推荐值,或者常见的错误配置。例如,引用[1]提到配置队列容量,这也是配置线程池时需要考虑的。此外,引用[5]可能包含一些使用教程的细节,需要确认是否有必要包含。 总结一下,回答的结构应该是:配置线程池Bean -> 启用异步支持 -> 在方法上指定线程池 -> 其他使用方式。同时,提供代码示例相关注意事项,如避免默认线程池的问题。</think>### 如何为Spring @Async指定自定义线程池 #### 1. 配置自定义线程池Bean 在Spring Boot中,通过`ThreadPoolTaskExecutor`定义线程池参数,并在配置类中声明为Bean: ```java @Configuration public class ThreadPoolConfig { @Bean("myExecutor") // Bean名称用于后续引用 public Executor customThreadPool() { ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor(); executor.setCorePoolSize(5); // 常驻线程数[^3] executor.setMaxPoolSize(10); // 最大线程数(队列满时触发) executor.setQueueCapacity(100); // 任务队列容量[^1] executor.setThreadNamePrefix("Async-"); executor.initialize(); return executor; } } ``` #### 2. 启用异步支持 在启动类添加`@EnableAsync`注解激活异步功能: ```java @EnableAsync // 必须添加[^3] @SpringBootApplication public class DemoApplication { public static void main(String[] args) { SpringApplication.run(DemoApplication.class, args); } } ``` #### 3. 使用指定线程池 在异步方法上通过`@Async("beanName")`显式指定线程池: ```java @Service public class AsyncService { @Async("myExecutor") // 指定自定义线程池[^2] public void processTask() { // 异步执行逻辑 } } ``` #### 4. 扩展应用场景 通过`CompletableFuture`结合自定义线程池: ```java CompletableFuture.runAsync(() -> { // 异步任务 }, customThreadPool); // 显式传入线程池[^2] ``` #### 关键注意事项 1. **避免默认线程池问题** Spring默认使用`SimpleAsyncTaskExecutor`(每次新建线程)[^4],高并发场景需自定义线程池控制资源 2. **参数配置建议** 核心线程数按CPU核数设定(如N核CPU设2N),队列容量根据任务特性选择(内存敏感型设小容量) 3. **线程池隔离策略** 可为不同业务类型配置独立线程池,如: ```java @Bean("orderExecutor") @Bean("paymentExecutor") ```
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值