SpringBoot-27- @Async实现异步调用rn什么是异步调用

SpringBoot-27- @Async实现异步调用

什么是异步调用

异步调用是相对于同步调用的,同步调用是按照顺序进行执行任务,只有上一个任务执行完成下一个任务才能执行,异步调用是指在按照顺序执行任务的过程中不需要等待任务结果的出现,就可以顺序执行下一个任务

异步处理的方式:

  • Java异步处理:Thread/Runnable、Callable/Future
  • Servlet 3.0异步处理: asyncSupported、AsyncContext
  • Spring MVC异步处理: @Async、AsyncTaskExecutor

SpringBoot自身没有对异步调用做很大的变动,基本还是使用SpringMVC的@Async

开启异步调用配置

@EnableAsync
@Configuration
public class MyEnableAsyncConfig {
}

注解:在使用**@EnableWebMvc**注解的时候也可以开启异步调用,但是在SpringBoot中使用异步调用会使得SpringBoot的AutoConfig一部分功能失效。

定义线程池

定义一个或者多个线程池

@EnableAsync
@Configuration
public class MyEnableAsyncConfig {
    @Bean(name = "threadPoolTaskExecutor1")
    public Executor taskExecutor1() {
        ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
        executor.setCorePoolSize(10);
        executor.setMaxPoolSize(20);
        executor.setQueueCapacity(200);
        executor.setKeepAliveSeconds(60);
        executor.setThreadNamePrefix("threadPoolTaskExecutor1-");
        executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
        return executor;
    }

    @Bean(name = "threadPoolTaskExecutor2")
    public Executor threadPoolTaskExecutor2() {
        ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
        executor.setCorePoolSize(10);
        executor.setMaxPoolSize(20);
        executor.setQueueCapacity(200);
        executor.setKeepAliveSeconds(60);
        executor.setThreadNamePrefix("threadPoolTaskExecutor2-");
        executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
        return executor;
    }
}

我们使用ThreadPoolTaskExecutor创建线程池,其参数配置如下:

  • CorePoolSize:设置核心线程数,线程池创建的时候创建线程的个数
  • MaxPoolSize:最大线程数,在换成队列满以后才会申请超过核心线程的线程
  • QueueCapacity:缓冲队列,用来缓冲执行任务的队列
  • KeepAliveSeconds:当超过了核心线程数之外的线程在空闲时间到达之后会被销毁
  • ThreadNamePrefix:线程名称前缀

定义异步调用方法

异步调用方法有两种一个是没有返回值的,一种是有返回值的,具体实现如下:

@Component
public class ComponentTask {

    public static Random random =new Random();

    /**
     * 无返回值
     */

    @Async("threadPoolTaskExecutor2")
    public void asyncMethodWithVoidReturnType_One() throws InterruptedException {
        System.out.println("开始做asyncMethodWithVoidReturnType_One");
        long start = System.currentTimeMillis();
        Thread.sleep(random.nextInt(1000));
        long end = System.currentTimeMillis();
        System.out.println("完成asyncMethodWithVoidReturnType_One,耗时:" + (end - start) + "毫秒"+"  threadname:"+Thread.currentThread().getName());


    }
    @Async("threadPoolTaskExecutor1")
    public void asyncMethodWithVoidReturnType_Two() throws InterruptedException {
        System.out.println("开始做asyncMethodWithVoidReturnType_Two");
        long start = System.currentTimeMillis();
        Thread.sleep(random.nextInt(2000));
        long end = System.currentTimeMillis();
        System.out.println("完成asyncMethodWithVoidReturnType_Two,耗时:" + (end - start) + "毫秒" +"  threadname:"+Thread.currentThread().getName());

    }
    @Async("threadPoolTaskExecutor1")
    public void asyncMethodWithVoidReturnType_Three() throws InterruptedException {
        System.out.println("开始做asyncMethodWithVoidReturnType_Three");
        long start = System.currentTimeMillis();
        Thread.sleep(random.nextInt(3000));
        long end = System.currentTimeMillis();
        System.out.println("完成asyncMethodWithVoidReturnType_Three,耗时:" + (end - start) + "毫秒""  threadname:"+Thread.currentThread().getName());

    }


    /**
     * 有返回值的
     * @return
     */

    @Async("threadPoolTaskExecutor1")
    public Future<String> asyncMethodWithReturnType_One() throws InterruptedException {
        System.out.println("开始asyncMethodWithReturnType_One");
        long start = System.currentTimeMillis();
        Thread.sleep(random.nextInt(10000));
        long end = System.currentTimeMillis();
        System.out.println("完成asyncMethodWithReturnType_One,耗时:" + (end - start) + "毫秒");
        return new AsyncResult<>("任务一完成");
    }
}

在多线程池的时候,我们需要在@Async()指定线程池名称**@Async(“threadPoolTaskExecutor1”)**

单元测试

@SpringBootTest
class SpringBootPart27ApplicationTests {
    @Autowired
    private ComponentTask componentTask;

    @Test
    void contextLoads() throws InterruptedException {
        componentTask.asyncMethodWithVoidReturnType_One();
        componentTask.asyncMethodWithVoidReturnType_Two();
        componentTask.asyncMethodWithVoidReturnType_Three();

        Thread.currentThread().join();

    }

}

在单元测试用例中,注入Task对象,并在测试用例中执行asyncMethodWithVoidReturnType_OneasyncMethodWithVoidReturnType_Two()asyncMethodWithVoidReturnType_Three()三个函数。

执行结果如下:

开始做asyncMethodWithVoidReturnType_One
开始做asyncMethodWithVoidReturnType_Two
开始做asyncMethodWithVoidReturnType_Three
完成asyncMethodWithVoidReturnType_One,耗时:435毫秒  threadname:threadPoolTaskExecutor2-1
完成asyncMethodWithVoidReturnType_Two,耗时:1885毫秒  threadname:threadPoolTaskExecutor1-1
完成asyncMethodWithVoidReturnType_Three,耗时:1904毫秒  threadname:threadPoolTaskExecutor1-2

如果您觉得本文不错,欢迎关注,点赞,收藏支持,您的关注是我坚持的动力!


原创不易,转载请注明出处,感谢支持!如果本文对您有用,欢迎转发分享!



原文始发于微信公众号(springboot葵花宝典):SpringBoot-27- @Async实现异步调用rn什么是异步调用

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/184348.html

(0)
小半的头像小半

相关推荐

发表回复

登录后才能评论
极客之音——专业性很强的中文编程技术网站,欢迎收藏到浏览器,订阅我们!