zoukankan      html  css  js  c++  java
  • SpringBoot中异步调用的使用

    一.简介

      异步调用是相对于同步调用而言的,同步调用是程序在执行时需要一步步执行代码,必须上一步执行完才能够进行下一步,而异步调用则不需要等待上一步执行完就可以继续执行。

    二.实现

      想实现异步调用,多线程就是实现的一种方式。我们可以实现Runable接口或者继承Thread类,或使用Executors线程池。

      在SpringBoot提供了很方便使用异步调用的方式,只需要两个注解就可以实现。

      在入口类添加@EnableAsync。

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

      Controller类。

    @RequestMapping("/TestController")
    @RestController
    public class TestController {
    
        @Autowired
        private AsyncTask asyncTask;
    
        @RequestMapping(value = "/doTask", method = RequestMethod.GET)
        public String doTask() throws InterruptedException{
            long currentTimeMillis = System.currentTimeMillis();
            asyncTask.task1();
            asyncTask.task2();
            asyncTask.task3();
            long currentTimeMillis1 = System.currentTimeMillis();
            return "task任务总耗时:"+(currentTimeMillis1-currentTimeMillis)+"ms";
    
        }
    }

      异步任务类。注意不能在Controller中直接调用有@Async注解的方法,否则会失效。需要创建一个类来使用@Async方法。异步类需要@Component注解,否则spring会扫描不到。在Controller中使用需要@Autowired注解来进行注入,不能直接new对象。

    @Component
    public class AsyncTask {
        @Async
        public void task1() throws InterruptedException{
            long currentTimeMillis = System.currentTimeMillis();
            Thread.sleep(1000);
            long currentTimeMillis1 = System.currentTimeMillis();
            System.out.println("task1任务耗时:"+(currentTimeMillis1-currentTimeMillis)+"ms");
        }
    
        @Async
        public void task2() throws InterruptedException{
            long currentTimeMillis = System.currentTimeMillis();
            Thread.sleep(2000);
            long currentTimeMillis1 = System.currentTimeMillis();
            System.out.println("task2任务耗时:"+(currentTimeMillis1-currentTimeMillis)+"ms");
        }
        @Async
        public void task3() throws InterruptedException{
            long currentTimeMillis = System.currentTimeMillis();
            Thread.sleep(3000);
            long currentTimeMillis1 = System.currentTimeMillis();
            System.out.println("task3任务耗时:"+(currentTimeMillis1-currentTimeMillis)+"ms");
        }
    }

      返回结果。

    //控制台
    task1任务耗时:1000ms
    task2任务耗时:2001ms
    task3任务耗时:3000ms
    
    //接口返回
    task任务总耗时:1ms

      如果想知道异步任务什么时候执行完,可以使用Fature回调方式来判断。

    @Component
    public class AsyncTask {
    
        @Async
        public Future<String> task1() throws InterruptedException{
            long currentTimeMillis = System.currentTimeMillis();
            Thread.sleep(1000);
            long currentTimeMillis1 = System.currentTimeMillis();
            System.out.println("task1任务耗时:"+(currentTimeMillis1-currentTimeMillis)+"ms");
            return new AsyncResult<String>("task1执行完毕");
        }
    
        @Async
        public Future<String> task2() throws InterruptedException{
            long currentTimeMillis = System.currentTimeMillis();
            Thread.sleep(2000);
            long currentTimeMillis1 = System.currentTimeMillis();
            System.out.println("task2任务耗时:"+(currentTimeMillis1-currentTimeMillis)+"ms");
            return new AsyncResult<String>("task2执行完毕");
        }
        @Async
        public Future<String> task3() throws InterruptedException{
            long currentTimeMillis = System.currentTimeMillis();
            Thread.sleep(3000);
            long currentTimeMillis1 = System.currentTimeMillis();
            System.out.println("task3任务耗时:"+(currentTimeMillis1-currentTimeMillis)+"ms");
            return new AsyncResult<String>("task3执行完毕");
        }
    }
    
    @RequestMapping("/TestController")
    @RestController
    public class TestController {
    
        @Autowired
        private AsyncTask asyncTask;
    
        @RequestMapping(value = "/doTask", method = RequestMethod.GET)
        public String doTask() throws InterruptedException{
            long currentTimeMillis = System.currentTimeMillis();
            Future<String> task1 = asyncTask.task1();
            Future<String> task2 = asyncTask.task2();
            Future<String> task3 = asyncTask.task3();
            String result = null;
            for (;;) {
                if(task1.isDone() && task2.isDone() && task3.isDone()) {
                    // 三个任务都调用完成,退出循环等待
                    break;
                }
                Thread.sleep(1000);
            }
            long currentTimeMillis1 = System.currentTimeMillis();
            result = "task任务总耗时:"+(currentTimeMillis1-currentTimeMillis)+"ms";
            return result;
        }
    }

      返回结果。

    //控制台
    task1任务耗时:1000ms  
    task2任务耗时:2001ms  
    task3任务耗时:3001ms  
    
    //接口返回
    task任务总耗时:4015ms

    三.总结

      1.异步调用适合任务较多、耗时较长的情况,比如导入数据。或者和主流程关系不大,可以另开线程执行,比如记录日志。

      2.注意在spring boot的启动文件上要添加@EnableAsync注解,要创建异步类来设置@Async注解的异步方法。

  • 相关阅读:
    深入浅出Mybatis系列(一)Mybatis入门
    LinkedList其实就那么一回事儿之源码分析
    深入浅出Mybatis系列(八)mapper映射文件配置之select、resultMap
    ArrayList其实就那么一回事儿之源码浅析
    springMVC 源码解读系列(一)初始化
    深入浅出Mybatis系列(三)配置详解之properties与environments(mybatis源码篇)
    深入浅出Mybatis系列(四)配置详解之typeAliases别名(mybatis源码篇)
    深入浅出Mybatis系列(六)objectFactory、plugins、mappers简介与配置
    深入浅出Mybatis系列(二)配置简介(mybatis源码篇)
    深入浅出Mybatis系列(七)mapper映射文件配置之insert、update、delete
  • 原文地址:https://www.cnblogs.com/shadoll/p/14431557.html
Copyright © 2011-2022 走看看