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

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 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 sendMailer(){
        String str = "";
        try {
            Map 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> futures = new ArrayList<>();
        Long start = System.currentTimeMillis();
        Map> 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> 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 使用带返回值的异步任务实现多线程并发任务[一])