• springboot使用@async实现异步线程池


    1.介绍

    工作中经常涉及异步任务,通常是使用多线程技术,比如线程池ThreadPoolExecutor,但使用Executors容易产生OOM,需要手动使用ThreadPoolExecutor创建线程池;在springboot使用 @async 可以实现异步调用,配置线程池参数,可以简单的实现多线程的线程池效果,从而简化开发,避免OOM;

    2.异步调用,无返回结果

    首先在启动类上加上@EnableAsync 注解

    @SpringBootApplication
    @EnableAsync
    public class AsyncApplication {
        public static void main(String[] args) {
            SpringApplication.run(AsyncApplication.class,args);
        }
    }
    

    在函数上标上@sync注解,表示异步调用

    @Async
    public void exec2(){
        try {
            Thread.sleep(3000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        log.info("exec2 执行完毕");
    }
    
    @GetMapping("exec2")
    public String exec2(){
        mainService.exec2();
        return "exec2";
    }
    

    测试:浏览器立即返回结果,3秒之后后台才打印输出日志

    2.异步调用,有返回值

    @Async
    public Future<String> exec3_1(){
        try {
            Thread.sleep(2500);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        log.info("exec3_1 执行完毕");
        return new AsyncResult<>("exec3_1");
    }
    
    @Async
    public Future<String> exec3_2(){
        try {
            Thread.sleep(3000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        log.info("exec3_2 执行完毕");
        return new AsyncResult<>("exec3_2");
    }
    
    @GetMapping("exec3")
    public String exec3() throws ExecutionException, InterruptedException {
        Future<String> exec3_1 = mainService.exec3_1();
        Future<String> exec3_2 = mainService.exec3_2();
    
        String result="";
    
        while (true){
            if(exec3_1.isDone() && exec3_2.isDone()){
                result=exec3_1.get()+"--"+exec3_2.get();
                break;
            }
        }
        return result;
    }
    

    测试:3秒后浏览器返回结果

    4.线程池

    在异步掉用中使用的@Async 注解,默认的线程池大小如下
    # 核心线程数
    spring.task.execution.pool.core-size=8  
    # 最大线程数
    spring.task.execution.pool.max-size=16
    # 空闲线程存活时间
    spring.task.execution.pool.keep-alive=60s
    # 是否允许核心线程超时
    spring.task.execution.pool.allow-core-thread-timeout=true
    # 线程队列数量
    spring.task.execution.pool.queue-capacity=100
    # 线程关闭等待
    spring.task.execution.shutdown.await-termination=false
    spring.task.execution.shutdown.await-termination-period=
    # 线程名称前缀
    spring.task.execution.thread-name-prefix=task-
    

    一般情况下,我们都需要手动创建线程池,使用 ThreadPoolTaskExecutor 类进行配置

    @Configuration
    public class PoolConfig {
    
        @Bean
        public TaskExecutor taskExecutor() {
            ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
            // 设置核心线程数
            executor.setCorePoolSize(10);
            // 设置最大线程数
            executor.setMaxPoolSize(15);
            // 设置队列容量
            executor.setQueueCapacity(20);
            // 设置线程活跃时间(秒)
            executor.setKeepAliveSeconds(60);
            // 设置默认线程名称
            executor.setThreadNamePrefix("zszxz-");
            // 设置拒绝策略
            executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
            // 等待所有任务结束后再关闭线程池
            executor.setWaitForTasksToCompleteOnShutdown(true);
            return executor;
        }
    }
    
  • 相关阅读:
    将Temporary文件夹里的Logo文件转移到Logo文件夹
    VS2013密匙
    Android SDK Tools 更新
    安装 phoneGap
    动态创建的DOM元素进行事件绑定
    不用安装Oracle_Client就能使用PLSQL_Developer
    POI 导出Excel
    mysql 通过IP连接
    微信 xml 转 Map
    uploadify springMVC
  • 原文地址:https://www.cnblogs.com/daikainan/p/14427162.html
Copyright © 2020-2023  润新知