springboot的异步任务:无返回值和有返回值问题

 更新时间:2023年07月20日 09:33:49   作者:kailly235  
这篇文章主要介绍了springboot的异步任务:无返回值和有返回值问题,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教

springboot异步任务:无返回值和有返回值

在想要异步执行的方法上加上@Async注解,在controller上加上@EnableAsync,即可。

注:这里的异步方法,只能在本类之外调用,在本类调用是无效的。

无返回值的异步任务

service实现部分:

@Service
public class AsyncService {
    @Async //想要异步执行的方法上加@Async 注解
    public void doNoReturn(){
        try {
            // 这个方法执行需要三秒
            Thread.sleep(3000);
            System.out.println("方法执行结束" + new Date());
        } catch (InterruptedException e) {
            e.printStackTrace();
    }
}

controller调用部分:

@RestController
@EnableAsync//调用异步任务的controller上加@EnableAsync注解
public class AsyncController {
    @Autowired
    private AsyncService asyncService;
    @RequestMapping(value = "/hello",method = RequestMethod.GET)
    public String testAsyncNoRetrun(){
        long start = System.currentTimeMillis();
         asyncService.doNoReturn();
         return String.format("任务执行成功,耗时{%s}", System.currentTimeMillis() - start);
    }

输出:

任务执行成功,耗时{4}

可见testAsyncNoRetrun()方法中 调用doNoReturn(),没等doNoReturn()执行完即返回。

有返回值的异步任务

有返回值的异步任务方法需要用Futrue变量把返回值封装起来。

service实现部分:

@Async
 public Future<String> doReturn(int i){
        try {
            // 这个方法需要调用500毫秒
            Thread.sleep(500);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        // 消息汇总
        return new AsyncResult<>(String.format("这个是第{%s}个异步调用的证书", i));
}

读取的时候要批量读取不能单独读取。

controller调用部分:

@GetMapping("/hi")
    public Map<String, Object> testAsyncReturn() throws ExecutionException, InterruptedException {
        long start = System.currentTimeMillis();
        Map<String, Object> map = new HashMap<>();
        List<Future<String>> futures = new ArrayList<>();
        for (int i = 0; i < 10; i++) {
            Future<String> future = asyncService.doReturn(i);
            futures.add(future);
        }
        List<String> response = new ArrayList<>();
        for (Future future : futures) {
            String string = (String) future.get();
            response.add(string);
        }
        map.put("data", response);
        map.put("消耗时间", String.format("任务执行成功,耗时{%s}毫秒", System.currentTimeMillis() - start));
        return map;
}

在浏览器输入地址:http://localhost:8080/hi

结果如下: 耗时500多毫秒的意思代表,springboot自带异步任务线程池是小于10的大小的

{"data":["这个是第{0}个异步调用的证书","这个是第{1}个异步调用的证书","这个是第{2}个异步调用的证书","这个是第{3}个异步调用的证书","这个是第{4}个异步调用的证书","这个是第{5}个异步调用的证书","这个是第{6}个异步调用的证书","这个是第{7}个异步调用的证书","这个是第{8}个异步调用的证书","这个是第{9}个异步调用的证书"],"消耗时间":"任务执行成功,耗时{508}毫秒"}

springboot的异步任务(带返回值和不带返回值的处理)

注意:在用异步任务之前先给启动类加@EnableAsync这个注解

新建异步任务包和在包里面建异步任务类

As.java异步类

package com.example.demo.async;
import org.springframework.scheduling.annotation.Async;
import org.springframework.scheduling.annotation.AsyncResult;
import org.springframework.stereotype.Component;
import java.util.concurrent.Future;
//注意:1、要把异步任务写进一个类里面而不能直接写在controller中
//      2、如果需要拿到结果,则需要在调用处判断全部的task.isDone()来确定异步任务的完成
@Component
//异步类注解,表明整个类的方法都是异步方法,如果把这个注解加在某一个方法上而不是某一个类则表明仅仅是这个方法才是异步方法
@Async
public class As {
    //下面是3个异步任务(不带返回值的)
    public void task1() throws InterruptedException {
        long begin=System.currentTimeMillis();
        Thread.sleep(3000l);
        long end=System.currentTimeMillis();
        System.out.println("任务1耗时"+(end-begin));
    }
    public void task2() throws InterruptedException {
        long begin=System.currentTimeMillis();
        Thread.sleep(2000l);
        long end=System.currentTimeMillis();
        System.out.println("任务2耗时"+(end-begin));
    }
    public void task3() throws InterruptedException {
        long begin=System.currentTimeMillis();
        Thread.sleep(1000l);
        long end=System.currentTimeMillis();
        System.out.println("任务3耗时"+(end-begin));
    }
    //下面是3个异步任务(带返回值的,可以在调用出取地返回值)
    public Future<String> task4() throws InterruptedException {
        long begin=System.currentTimeMillis();
        Thread.sleep(3000l);
        long end=System.currentTimeMillis();
        return new AsyncResult<String>("任务4耗时"+(end-begin));
    }
    public Future<String> task5() throws InterruptedException {
        long begin=System.currentTimeMillis();
        Thread.sleep(2000l);
        long end=System.currentTimeMillis();
        return new AsyncResult<String>("任务5耗时"+(end-begin));
    }
    public Future<String> task6() throws InterruptedException {
        long begin=System.currentTimeMillis();
        Thread.sleep(1000l);
        long end=System.currentTimeMillis();
        return new AsyncResult<String>("任务6耗时"+(end-begin));
    }
}

controller测试控制器

package com.example.demo.controller;
import com.example.demo.async.As;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;
@RestController
public class He {
	//注入异步类
    @Autowired
    private As as;
    //测试异步任务没带返回值的,直接主线程瞬间就通过了
    @RequestMapping("/as")
    public Object as() throws InterruptedException {
        long begin=System.currentTimeMillis();
        as.task1();
        as.task2();
        as.task3();
        long end=System.currentTimeMillis();
        return "总耗时+"+(end-begin);
    }
    //测试异步任务带返回值的,总耗时是最慢的那个任务的耗时
    @RequestMapping("/asHava")
    public Object ash() throws InterruptedException, ExecutionException {
        long begin=System.currentTimeMillis();
        Future<String> task4=as.task4();
        Future<String> task5=as.task5();
        Future<String> task6=as.task6();
        //先小堵塞主线程一会,用以拿到异步任务返回值
        while (!(task4.isDone()&&task5.isDone()&&task6.isDone())){
        }
        long end=System.currentTimeMillis();
        //取得异步任务的返回值并查看总耗时
        return "总耗时+"+(end-begin)+"   task4结果:"+task4.get()+"  task5结果:"+task5.get()+"  task6结果:"+task6.get();
        //结果是3s左右,因为进入接口,三个异步任务瞬间开启,再瞬间到while这儿堵起
        //由于三个异步任务几乎是同时开启的,所以等最慢的那个异步任务完成以后,肯定所有的异步任务都完成了
        //所以while这时才都为true,那么放开while,所以结果就是最慢的那个异步任务的时间
        //如果说不用这种异步取值而用同步的话,那么时间就是1+2+3就是6s左右,而不是最慢的那个任务的时间
    }
}

总结

以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。

相关文章

  • SpringBoot集成Redisson实现延迟队列的场景分析

    SpringBoot集成Redisson实现延迟队列的场景分析

    这篇文章主要介绍了SpringBoot集成Redisson实现延迟队列,本文通过场景分析实例代码相结合给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2021-04-04
  • JAVA获得包含0-9、a-z、A-Z范围内字符串的的随机数实例

    JAVA获得包含0-9、a-z、A-Z范围内字符串的的随机数实例

    这篇文章主要介绍了JAVA获得包含0-9、a-z、A-Z范围内字符串的的随机数实例,包含随机数字、随机字符串的获取方法,需要的朋友可以参考下
    2014-07-07
  • mybatis postgresql 批量删除操作方法

    mybatis postgresql 批量删除操作方法

    PostgreSQL是一种特性非常齐全的自由软件的对象-关系型数据库管理系统(ORDBMS),这篇文章主要介绍了mybatis postgresql 批量删除操作,需要的朋友可以参考下
    2020-02-02
  • MyBatis中多对一和一对多数据的处理方法

    MyBatis中多对一和一对多数据的处理方法

    这篇文章主要介绍了MyBatis中多对一和一对多数据的处理,本文通过示例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2023-01-01
  • spring cloud 配置中心客户端启动遇到的问题

    spring cloud 配置中心客户端启动遇到的问题

    这篇文章主要介绍了spring cloud 配置中心客户端启动遇到的问题,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2021-09-09
  • Java中的IO读写原理详解

    Java中的IO读写原理详解

    这篇文章主要介绍了Java中的IO读写原理,IO是指输入和输出操作的技术,它提供了一组用于读取和写入数据的类,以及用于处理字符和字节数据的接口,这些类和接口可以用于读取和写入文件、网络流、内存缓冲区等各种数据源和目标,需要的朋友可以参考下
    2023-08-08
  • Java语言实现数据结构栈代码详解

    Java语言实现数据结构栈代码详解

    这篇文章主要介绍了Java语言实现数据结构栈代码详解,简单介绍了栈的概念,然后分享了线性栈和链式栈的Java代码,具有一定参考价值,需要的朋友可以了解下。
    2017-11-11
  • maven环境变量配置讲解

    maven环境变量配置讲解

    这篇文章主要介绍了maven环境变量配置讲解,本篇文章通过简要的案例,讲解了该项技术的了解与使用,以下就是详细内容,需要的朋友可以参考下
    2021-08-08
  • Java中channel用法总结

    Java中channel用法总结

    这篇文章主要介绍了Java中channel用法,较为详细的总结了channel的定义、类型及使用技巧,需要的朋友可以参考下
    2015-06-06
  • java 反射和动态代理详解及实例代码

    java 反射和动态代理详解及实例代码

    这篇文章主要介绍了java 反射和动态代理详解及实例代码的相关资料,需要的朋友可以参考下
    2016-09-09

最新评论