java-基于springboot框架实现线程池异步调用多系统接口

上一篇文章中,介绍了通过ThreadPoolExecutor和Callable实现异步调用多系统接口的思路和方式。这篇基于springboot框架,如何实现异步的调用。

 

SpringDemoApplication.java 

启动类需要添加@EnableAsync注解。

@EnableAsync
@SpringBootApplication
public class SpringDemoApplication {

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

}

 

ThreadPoolConfig.java

配置类里配置线程池参数。

@Configuration
public class ThreadPoolConfig {
    private static final int THREAD = Runtime.getRuntime().availableProcessors() + 1;  // 处理器个数+1
    public static int corePoolSize = 5;
    private int maxPoolSize = 10;
    private int queueCapacity = 1024;
    private int keepAliveSeconds = 300;
    private static final String threadNamePrefix = "async-thread-";

    @Bean(name = "threadPoolTaskExecutor")
    public ThreadPoolTaskExecutor threadPoolTaskExecutor() {
        ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
        // 设置线程池参数
        executor.setMaxPoolSize(maxPoolSize);
        executor.setCorePoolSize(corePoolSize);
        executor.setQueueCapacity(queueCapacity);
        executor.setKeepAliveSeconds(keepAliveSeconds);
        executor.setThreadNamePrefix(threadNamePrefix);
        executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());

        executor.initialize();  // 初始化
        return executor;
    }
}

 

AsyncSystemService.java

service层注解配置类。

@Async("threadPoolTaskExecutor")  // value值与声明的配置类注册的Bean名一致
@Service
public class AsyncSystemService {

//    @Async("threadPoolTaskExecutor")  // 配置在方法上表示方法异步,配置在类上表示类异步
    public Future<List<Result>> system1(String params, String url) throws InterruptedException {
        System.out.println("begin-----" + Thread.currentThread().getName() + "-----" + new Date() + " system1()");
        List<Result> res = new ArrayList<>();
        /**
         * 此处为调取各系统接口,并获取返回结果,封装至res内的逻辑
         */
        Thread.sleep(5000);  // 为体现出异步效果,加入延时5s的逻辑;实际业务中删除
        System.out.println("end-----" + Thread.currentThread().getName() + "-----" + new Date() + " system1()");
        return new AsyncResult<>(res);
    }
    
//    @Async("threadPoolTaskExecutor")
    public Future<List<Result>> system2(String params, String url) throws InterruptedException {
        System.out.println("begin-----" + Thread.currentThread().getName() + "-----" + new Date() + " system2()");
        List<Result> res = new ArrayList<>();
        /**
         * 此处为调取各系统接口,并获取返回结果,封装至res内的逻辑
         */
        Thread.sleep(5000);  // 为体现出异步效果,加入延时5s的逻辑;实际业务中删除
        System.out.println("end-----" + Thread.currentThread().getName() + "-----" + new Date() + " system2()");
        return new AsyncResult<>(res);
    }
}

 

AsyncSystemController.java

controller层。

@RestController
@RequestMapping("/async")
public class AsyncSystemController {
    @Autowired
    private AsyncSystemService asyncSystemService;


    @GetMapping("/allResult")
    public List<Result> getAllResult() throws InterruptedException, ExecutionException {
        LocalDateTime beginTime = LocalDateTime.now();
        List<Result> res = new ArrayList<>();  // 汇总结果

        Future<List<Result>> future1 = asyncSystemService.system1("params1", "url1");  // 异步访问系统1
        Future<List<Result>> future2 = asyncSystemService.system2("params2", "url2");  // 异步访问系统2

        List<Future<List<Result>>> futureList = new ArrayList<>();
        futureList.add(future1);
        futureList.add(future2);

        for (Future<List<Result>> futureItem : futureList) {
            while (true) {
                if (futureItem.isDone() && !futureItem.isCancelled()) {  // 当前任务结束,且不是被取消的情况,获取任务返回值
                    res.addAll(futureItem.get());
                    break;  // 获取结果后,一定记得要break,跳出当前线程任务轮询是否结束的循环
                } else {  
                    Thread.sleep(1);  // 当前线程未结束时,每次轮询休息1毫秒,避免CPU高速轮询
                }
            }
        }

        Long timeConsuming = Duration.between(beginTime, LocalDateTime.now()).toMillis();
        System.out.println("时间消耗:" + timeConsuming);
        return res;
    }
}

 

运行打印结果:

 

可以看出:两个系统分两个线程,同时执行线程任务。总耗时为max(t1, t2)。

 

posted @ 2024-12-11 11:55  DoubleFishes  阅读(11)  评论(0编辑  收藏  举报