记录第一次使用 @Async 和 @EnableAsync 写 java 的异步代码

1,577 阅读1分钟

被赶鸭子上架写 java ,框架都不会用,这篇纯属自己的笔记,大佬们就不用看了~~

创建一个线程池,并且自定义拒绝策略

@Configuration
public class TaskExecutorConfig {

    @Value("#{10}")
    private Integer corePoolSize;
    @Value("#{100}")
    private Integer maxPoolSize;
    @Value("#{200}")
    private Integer queueCapacity;
    @Value("#{10}")
    private Integer keepAliveSeconds;
    @Value("#{'taskExecutor'}")
    private String threadNamePrefix;

    @Bean
    public TaskExecutor taskExecutor() {
        ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
        // 设置核心线程数
        executor.setCorePoolSize(corePoolSize);
        // 设置最大线程数
        executor.setMaxPoolSize(corePoolSize);
        // 设置队列容量
        executor.setQueueCapacity(queueCapacity);
        // 设置线程活跃时间(秒)
        executor.setKeepAliveSeconds(keepAliveSeconds);
        // 设置默认线程名称
        executor.setThreadNamePrefix(threadNamePrefix);
        // 设置拒绝策略
        executor.setRejectedExecutionHandler(new CustomAbortPolicy());
        // 等待所有任务结束后再关闭线程池
        executor.setWaitForTasksToCompleteOnShutdown(true);
        //设置线程池中 任务的等待时间,如果超过这个时间还没有销毁就 强制销毁
        executor.initialize();
        return executor;
    }

}


@Slf4j
class CustomAbortPolicy implements RejectedExecutionHandler {
    public void rejectedExecution(Runnable r, ThreadPoolExecutor executor) {
        if (!executor.isShutdown()) {
            try {
                log.error("FULL-->>线程池已满,执行拒绝策略");
                executor.getQueue().put(r);
            } catch (InterruptedException e) {
                log.error("interruptedException=" + e);
            }
        }
    }
}

在某个 Service 类需要异步的方法上加注解 @Async("taskExecutor") ,且如果有返回值,返回类型应该为 Future<>

@Async("taskExecutor")
public Future<String> findTown(JSONObject jsonObject) throws IOException {
    if (jsonObject.containsKey("town") && !StringUtils.isEmpty(jsonObject.get("town").toString().trim()))
        return new AsyncResult<>(jsonObject.get("town").toString());
    return new AsyncResult<>("");
}

如果有多个返回值异步,可以将返回的 Future<> 结果都保存在一个数组中,然后遍历数组,从每个 Future<> 中取出结果值

// 存放 Future 结果的数组
List<Future<String>> list = new ArrayList<>();
// 存放返回结果数组
List<String> result = new ArrayList<>();
// 对每个地址进行街道定位
for(String address :addresses)
    list.add(findTownService.findTown((JSONObject) jsonObject.get(address.trim())));
// 获取返回结果
for (Future<String> r : list)
    result.add(r.get());
    

要记得在启动类上加注解 @EnableAsync

@EnableAsync
public class DataManagementApplication extends SpringBootServletInitializer {

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

}