zoukankan      html  css  js  c++  java
  • coding++:springboot 多线程@Async

    线程池ThreadPoolExecutor,它的执行规则如下:

    在Springboot中对其进行了简化处理,只需要配置一个类型为 java.util.concurrent.TaskExecutor或其子类的bean,并在配置类或直接在程序入口类上声明注解@EnableAsync。

    调用也简单,在由Spring管理的对象的方法上标注注解@Async,显式调用即可生效。

    一般使用Spring提供的ThreadPoolTaskExecutor类。

    @Bean
     public Executor myTaskAsyncPool() {
            ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
            //核心线程池大小
            executor.setCorePoolSize(config.getCorePoolSize());
            //最大线程数
            executor.setMaxPoolSize(config.getMaxPoolSize());
            //队列容量
            executor.setQueueCapacity(config.getQueueCapacity());
            //活跃时间
            executor.setKeepAliveSeconds(config.getKeepAliveSeconds());
            //线程名字前缀
            executor.setThreadNamePrefix("MyExecutor-");
    
            // setRejectedExecutionHandler:当pool已经达到max size的时候,如何处理新任务
            // CallerRunsPolicy:不在新线程中执行任务,而是由调用者所在的线程来执行
            executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
            // 等待所有任务结束后再关闭线程池
            //executor.setWaitForTasksToCompleteOnShutdown(true);
            executor.initialize();
            return executor;
        }

    XML 配置:

       <!-- spring线程池 -->
        <bean id="taskExecutor" class="org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor">
            <!-- 核心线程数  -->
            <property name="corePoolSize" value="10"/>
            <!-- 最大线程数 -->
            <property name="maxPoolSize" value="200"/>
            <!-- 队列最大长度 >=mainExecutor.maxSize -->
            <property name="queueCapacity" value="10"/>
            <!-- 线程池维护线程所允许的空闲时间 -->
            <property name="keepAliveSeconds" value="20"/>
            <!-- 线程池对拒绝任务(无线程可用)的处理策略 -->
            <property name="rejectedExecutionHandler">
                <bean class="java.util.concurrent.ThreadPoolExecutor$CallerRunsPolicy"/>
            </property>
        </bean>

    测试调用:

    @Component
    public class Hello {
        @Async
        public void sayHello(String name) {
            LoggerFactory.getLogger(Hello.class).info(name + ":Hello World!");
        }
    }

    执行结果:

    进阶:

    有时候我们不止希望异步执行任务,还希望任务执行完成后会有一个返回值,在java中提供了Future泛型接口,用来接收任务执行结果,springboot也提供了此类支持,

    使用实现了ListenableFuture接口的类如AsyncResult来作为返回值的载体。比如上例中,我们希望返回一个类型为String类型的值,可以将返回值改造为:

        @Async
        public ListenableFuture<String> sayHello(String name) {
            String res = name + ":Hello World!";
            LoggerFactory.getLogger(Hello.class).info(res);
            return new AsyncResult<>(res);
        }

    调用返回值:

        @Autowired
        private Hello hello;
    
        // 阻塞调用
        hello.sayHello("yan").get();
        // 限时调用
        hello.sayHello("yan").get(1, TimeUnit.SECONDS)

    扩充:

    实际上,@Async还有一个参数,通过Bean名称来指定调用的线程池-比如上例中设置的线程池参数不满足业务需求,可以另外定义合适的线程池,

    调用时指明使用这个线程池-缺省时springboot会优先使用名称为'taskExecutor'的线程池,如果没有找到,才会使用其他类型为TaskExecutor或其子类的线程池。

  • 相关阅读:
    浅谈Java并发编程系列(八)—— LockSupport原理剖析
    mac上安装MongoDB
    在Mac上搭建Python虚拟环境
    Django项目上传到AWS服务器上
    Django部署
    Getting Started with Django Rest Framework and AngularJS
    Tutorial 7: Schemas & client libraries
    Tutorial 6: ViewSets & Routers
    Tutorial 5: Relationships & Hyperlinked APIs
    Tutorial 4: Authentication & Permissions
  • 原文地址:https://www.cnblogs.com/codingmode/p/12705818.html
Copyright © 2011-2022 走看看