zoukankan      html  css  js  c++  java
  • springboot之异步任务

    springboot之异步任务

    启动类:添加@EnableAsync注解

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

    异步任务执行类 添加@Async注解

    import java.util.concurrent.Future;
     
    import org.springframework.scheduling.annotation.Async;
    import org.springframework.scheduling.annotation.AsyncResult;
    import org.springframework.stereotype.Component;
     
    /**
     * 功能描述:异步任务业务类(@Async也可添加在方法上,@Async放在类上,表示类内方法皆为异步方法)
     */
    @Component
    @Async("taskExecutor")//使用自己的线程池记得括号内填写线程池bean的名字,详见下边线程池配置;如果使用默认线程池,则直接使用@Async
    public class AsyncTask {
        
     
        //获取异步结果
        public Future<String> task4() throws InterruptedException{
            long begin = System.currentTimeMillis();
            Thread.sleep(2000L);
            long end = System.currentTimeMillis();
            System.out.println("任务4耗时="+(end-begin));
            return new AsyncResult<String>("任务4");
        }
        
        
        public Future<String> task5() throws InterruptedException{
            long begin = System.currentTimeMillis();
            Thread.sleep(3000L);
            long end = System.currentTimeMillis();
            System.out.println("任务5耗时="+(end-begin));
            return new AsyncResult<String>("任务5");
        }
        
        public Future<String> task6() throws InterruptedException{
            long begin = System.currentTimeMillis();
            Thread.sleep(1000L);
            long end = System.currentTimeMillis();
            System.out.println("任务6耗时="+(end-begin));
            return new AsyncResult<String>("任务6");
        }
            
    }

    异步线程池

    package com.boot.common.conf;
     
    import java.util.concurrent.ThreadPoolExecutor;
     
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration;
    import org.springframework.scheduling.annotation.EnableAsync;
    import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
     
    /**
     * 线程池配置(线程池可以不配置,使用默认线程池,注意:在异步方法或类添加@Async注解是:@Async;如果自己配置了线程池,异步方法或类使用自己配置的线程池,则注解应为:@Async("taskExecutor")括号内为自己配置的线程池对象bean的名字)
     * @author zhh
     *
     */
    @Configuration
    @EnableAsync
    public class ThreadPoolTaskConfig {
        
        private static final int corePoolSize = 10;               // 核心线程数(默认线程数)线程池创建时候初始化的线程数
        private static final int maxPoolSize = 100;                // 最大线程数 线程池最大的线程数,只有在缓冲队列满了之后才会申请超过核心线程数的线程
        private static final int keepAliveTime = 10;            // 允许线程空闲时间(单位:默认为秒)当超过了核心线程之外的线程在空闲时间到达之后会被销毁
        private static final int queueCapacity = 200;            // 缓冲队列数 用来缓冲执行任务的队列
        private static final String threadNamePrefix = "Async-Service-"; // 线程池名前缀 方便我们定位处理任务所在的线程池
        
        @Bean("taskExecutor") // bean的名称,默认为首字母小写的方法名
        public ThreadPoolTaskExecutor taskExecutor(){
            ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
            executor.setCorePoolSize(corePoolSize);   
            executor.setMaxPoolSize(maxPoolSize);
            executor.setQueueCapacity(queueCapacity);
            executor.setKeepAliveSeconds(keepAliveTime);
            executor.setThreadNamePrefix(threadNamePrefix);
            
            // 线程池对拒绝任务的处理策略 采用了CallerRunsPolicy策略,当线程池没有处理能力的时候,该策略会直接在 execute 方法的调用线程中运行被拒绝的任务;如果执行程序已关闭,则会丢弃该任务
            executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
            // 初始化
            executor.initialize();
            return executor;
        }
    }

    异步任务调用

    import java.util.concurrent.Future;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.web.bind.annotation.GetMapping;
    import org.springframework.web.bind.annotation.RequestMapping;
    import org.springframework.web.bind.annotation.RestController;
    import com.jincou.task.AsyncTask;
    import com.jincou.util.JsonData;
    
    @RestController
    @RequestMapping("/api/v1")
    public class UserController {
        
        @Autowired
        private AsyncTask task;
        
        @GetMapping("async_task")
        public JsonData exeTask() throws InterruptedException{
            
            long begin = System.currentTimeMillis();
            
            Future<String> task4 = task.task4();
            Future<String> task5 = task.task5();
            Future<String> task6 = task.task6();
            
            /**
             *如果需要监控异步任务是否完成,可以使用以下方式
            **/
            //如果都执行完成就可以跳出循环,isDone方法如果此任务完成,true
            for(;;){
                if (task4.isDone() && task5.isDone() && task6.isDone()) {
                    break;
                }
            }
           
            long end = System.currentTimeMillis();    
            long total = end-begin;
            System.out.println("执行总耗时="+total);
            return JsonData.buildSuccess(total);
        }    
    }

    注意事项:

    优点:使用异步任务比同步任务耗时少,提高后台处理性能。
    如下方式会使@Async失效
    一、异步方法使用static修饰
    二、异步类没有使用@Component注解(或其他注解)导致spring无法扫描到异步类
    三、异步方法不能与调用异步方法的方法在同一个类中
    四、类中需要使用@Autowired或@Resource等注解自动注入,不能自己手动new对象
    五、如果使用SpringBoot框架必须在启动类中增加@EnableAsync注解
    六、在Async 方法上标注@Transactional是没用的。 在Async 方法调用的方法上标注@Transactional 有效。

    原文摘自:https://blog.csdn.net/k0307x1990y/article/details/91950584

  • 相关阅读:
    互操作
    Rx基础
    数据流块基础
    C# 一个帮您理解回调函数的例子(新手必看)
    C# 多线程之通过Timer开启线程的例子
    C# 利用委托事件进行窗体间的传值(新手必看)
    C#XML文件操作随笔
    C# 委托学习笔记
    c# 关于抓取网页源码后中文显示乱码的原因分析和解决方法
    c# 异步编程 使用回调函数例子
  • 原文地址:https://www.cnblogs.com/fujingtao5470/p/12666747.html
Copyright © 2011-2022 走看看