美文网首页
springboot2.x 使用带返回值的异步任务实现多线程并发

springboot2.x 使用带返回值的异步任务实现多线程并发

作者: 骑蚂蚁上高速_jun | 来源:发表于2020-08-31 19:24 被阅读0次

    1.在启动类上使用注解 @EnableAsync开启异步任务

    @SpringBootApplication
    @EnableAsync // 开启异步任务[多线程下运行]
    @EnableScheduling // 开启定时任务
    public class WangjunApplication {
    
        public static void main(String[] args) {
            // 启动 springboot 程序
            SpringApplication.run(WangjunApplication.class, args);
        }
    
    }
    
    1. 创建SystemUtils 工具类, 用于辅助测试
      实际结果告诉我们, 两个异步任务,是在同一个进程中,不同线程中运行
    package cn.utils;
    
    import java.lang.management.ManagementFactory;
    import java.lang.management.RuntimeMXBean;
    
    public class SystemUtils
    {
    
        // 获取当前运行的进程 id
        public static int getProcessID() {
            RuntimeMXBean runtimeMXBean = ManagementFactory.getRuntimeMXBean();
            return Integer.valueOf(runtimeMXBean.getName().split("@")[0])
                    .intValue();
        }
    
        
        // 获取当前运行的线程 id
        public static Long getThreadID(){
            return Thread.currentThread().getId();
        }
    }
    
    
    1. 创建异步执行方法
    package cn.services;
    
    import cn.utils.SystemUtils;
    import org.springframework.scheduling.annotation.Async;
    import org.springframework.scheduling.annotation.AsyncResult;
    import org.springframework.stereotype.Service;
    import java.util.HashMap;
    import java.util.Map;
    import java.util.concurrent.Future;
    
    @Service
    public class IndexServices
    {
        /**
         * 异步发送短信
         * @return
         */
        @Async
        public Future<Boolean> sendSms(){
            String str = "";
            try {
                Thread.sleep(3000);
                str =  "短信发送完成当前时间戳是: "+System.currentTimeMillis() + "当前进程id="+SystemUtils.getProcessID()+ " 当前线程id="+SystemUtils.getThreadID();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println(str);
            return new AsyncResult<>(true);
    
        }
    
        /**
         * 异步发送邮件
         * @return
         */
        @Async
        public Future<Boolean> sendMailer(){
            String str = "";
            try {
                Map<String,Object> map = new HashMap<>();
    
                Thread.sleep(8000);
                str = "邮件发送完成当前时间戳是: "+System.currentTimeMillis() + "当前进程id="+ SystemUtils.getProcessID() + " 当前线程id="+SystemUtils.getThreadID();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println(str);
            return new AsyncResult<>(false);
        }
    }
    
    1. 调用 异步方法测试 在controoler中调用
     @GetMapping("v2")
        public String v2() throws ExecutionException, InterruptedException {
            //List<Future<String>> futures = new ArrayList<>();
            Long start = System.currentTimeMillis();
            Map<String,Future<Boolean>> futures = new HashMap<>();
    
            String str= "当前运行的主进程id="+ SystemUtils.getProcessID() + " 当前运行的线程是 : "+SystemUtils.getThreadID();
            System.out.println(str);
    
            futures.put("sendSms",indexServices.sendSms());// 发送短线
            futures.put("sendMailer",indexServices.sendMailer()); // 发送邮件
    
            for (Map.Entry<String, Future<Boolean>> entry: futures.entrySet()) {
                // 批量读取异步任务结果,否则达不到效果
                System.out.println( entry.getKey() + " 发送的结果是 :  " + entry.getValue().get());
            }
    
            Long end = System.currentTimeMillis();
            Long diff = end-start;
            System.out.println("时间差是 : "+diff + "; 当前时间戳是:"+end);
            return "";
        }
    

    重要的事情说三遍:

    一定要批量读取结果, 否则不能达到异步的效果!!

    一定要批量读取结果, 否则不能达到异步的效果!!

    一定要批量读取结果, 否则不能达到异步的效果!!

    实际结果告诉我们, 两个异步任务,是在同一个进程中,不同线程中运行

    相关文章

      网友评论

          本文标题:springboot2.x 使用带返回值的异步任务实现多线程并发

          本文链接:https://www.haomeiwen.com/subject/kgiedktx.html