zoukankan      html  css  js  c++  java
  • SpringBoot 异步任务处理

    SpringBoot配置异步任务
    有些业务是不需要你同步去操作的, 例如: 适用于处理log、发送邮件、短信……等
    我们不能因为短信没发出去而没有执行接下来的业务逻辑, 这个时候我们就应该去把这些耗时的任务弄成异步的

    首先要在启动类里面增加如下注解
    @EnableAsync
    定义异步任务类并使用@Component标记组件被容器扫描,异步方法加上@Async
    如果整个类的操作都是异步的话 @Async 可以给类加上, 要把异步任务封装到类里面,不能直接写到Controller

    package com.cj.tool.comtool.controller;
     
    import com.cj.tool.comtool.task.AsyncTask;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.web.bind.annotation.GetMapping;
    import org.springframework.web.bind.annotation.RestController;
     
    @RestController
    public class TestTaskController {
     
        @Autowired
        private AsyncTask asyncTask;
     
     
        // 直接调起异步任务。正常执行肯定是堵塞的
        @GetMapping("/api/v1/test_task")
        public long testTask() throws InterruptedException {
     
            long begin = System.currentTimeMillis();
     
            asyncTask.task1();
            asyncTask.task2();
            asyncTask.task3();
     
            long end = System.currentTimeMillis();
     
            System.out.println("Controller 执行时间" + (end - begin));
     
     
            return end - begin;
        }
     
    }
    

      




    // 直接调起异步任务。正常执行肯定是堵塞的

    package com.cj.tool.comtool.task;
     
    import org.springframework.scheduling.annotation.Async;
    import org.springframework.stereotype.Component;
     
    @Component
    @Async
    public class AsyncTask {
     
        public void task1() throws InterruptedException {
            long begin = System.currentTimeMillis();
            Thread.sleep(1000);
            long end = System.currentTimeMillis();
            System.out.println("task1耗时:"+ (end - begin));
        }
     
        public void task2() throws InterruptedException {
            long begin = System.currentTimeMillis();
            Thread.sleep(2000);
            long end = System.currentTimeMillis();
            System.out.println("task2耗时:"+ (end - begin));
        }
     
        public void task3() throws InterruptedException {
            long begin = System.currentTimeMillis();
            Thread.sleep(3000);
            long end = System.currentTimeMillis();
            System.out.println("task3耗时:"+ (end - begin));
        }
     
     
    }
    

      


    可以看到在AsyncTask里面都是有sleep的, 但是我们使用了异步


    Controller执行时间 是先输出的, 我们的任务去开另外的线程执行, 这样大大增加了我们的程序效率, 在项目里面合适使用异步任务, 可以大大提高我们的QPS

    获取异步返回数据
    上面例子虽然解决了堵塞的问题, 但是有的时候我们希望获取异步任务的返回结果, 再进行后续工作。放心 这个也有方案

    添加异步返回任务

    public Future<String> task4() throws InterruptedException {
            long begin = System.currentTimeMillis();
            Thread.sleep(4000);
            long end = System.currentTimeMillis();
            System.out.println("task4耗时:"+ (end - begin));
            return new AsyncResult<>("Task4的数据");
        }
     
        public Future<Integer> task5() throws InterruptedException {
            long begin = System.currentTimeMillis();
            Thread.sleep(5000);
            long end = System.currentTimeMillis();
            System.out.println("task5耗时:"+ (end - begin));
            return new AsyncResult<>(123);
        }
     
        public Future<String> task6() throws InterruptedException {
            long begin = System.currentTimeMillis();
            Thread.sleep(6000);
            long end = System.currentTimeMillis();
            System.out.println("task6耗时:"+ (end - begin));
            return new AsyncResult<>("Task6的数据");
        }
    @GetMapping("/api/v1/test_task")
        public long testTask() throws InterruptedException, ExecutionException {
            long begin = System.currentTimeMillis();
     
    //        asyncTask.task1();
    //        asyncTask.task2();
    //        asyncTask.task3();
     
            Future<String> task4Result = asyncTask.task4();
            Future<Integer> task5Result = asyncTask.task5();
            Future<String> task6Result = asyncTask.task6();
     
            // 等每个任务执行完了就跳出
            for (;;) {
                if (task4Result.isDone() && task5Result.isDone() && task6Result.isDone()) {
                    break;
                }
            }
            
            // 获取返回结果
            String task4res = task4Result.get();
            int task5res = task5Result.get();
     
            System.out.println(task4res);
            System.out.println(task5res);
     
            long end = System.currentTimeMillis();
     
            System.out.println("Controller 执行时间" + (end - begin));
     
            return end - begin;
        }


    说一下流程

    1)增加Future<String> 返回结果需呀 new AsyncResult<String>("task执行完成");

    2)如果需要拿到结果 需要判断全部的 task.isDone(), 然后再task.get() 获取返回数据

    效果

    可以看到 还是异步的, 最长耗时6000, 这样就可以应对不同的业务了, 如果是同步的话肯定需要 15000



  • 相关阅读:
    家谱树 x
    codevs 1231 最优布线问题 x(find函数要从娃娃抓起系列)
    洛谷 P1546 最短网络 Agri-Net x
    codevs 5969 [AK]刻录光盘x
    家谱(gen)x
    [POJ2594]Treasure Exploration(最小路径覆盖变种,floyd算法,匈牙利算法)
    [HDOJ5855]Less Time, More profit(最大权闭合子图,二分,最大流)
    [HDOJ1054]Strategic Game(最小点覆盖,最大二分匹配,HK算法)
    [HDOJ3829]Cat VS Dog(最大独立集)
    [HDOJ3488]Tour(二分图最小匹配,KM算法)
  • 原文地址:https://www.cnblogs.com/xiadongqing/p/15468934.html
Copyright © 2011-2022 走看看