springbot2.x集成@Async

本文详细探讨了在Spring框架下如何实现异步编程,包括通过接口实现@Async功能,直接在Controller中尝试异步方法的可行性,以及在Service中调用异步方法的正确方式。并介绍了在调用异步方法的方法上添加@Async注解来优化异步执行流程。

1. 最普通的接口类实现@Async

1.1 启动类配置,主要添加:@EnableAsync

1.2 写一个方法和接口实现异步方法

service:

public interface MyAsyncService {
    void doTaskOne();
    void doTaskTwo();
    void doTaskThree();
}

serviceImpl:

package com.pf.org.cms.hcg.system.service.impl;

import com.pf.org.cms.hcg.system.service.MyAsyncService;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;

import java.util.Random;

@Service
public class MyAsyncImpl implements MyAsyncService {
    public static Random random = new Random();

    @Async
    @Override
    public void doTaskOne() {
        System.out.println("开始做任务一");
        long start = System.currentTimeMillis();
        try {
            Thread.sleep(random.nextInt(10000));
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        long end = System.currentTimeMillis();
        System.out.println("完成任务一,耗时:" + (end - start) + "毫秒");

    }


    @Override
    @Async
    public void doTaskTwo() {
        System.out.println("开始做任务二");
        long start = System.currentTimeMillis();
        try {
            Thread.sleep(random.nextInt(10000));
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        long end = System.currentTimeMillis();
        System.out.println("完成任务二,耗时:" + (end - start) + "毫秒");
    }

    @Override
    @Async
    public void doTaskThree() {
        System.out.println("开始做任务三");
        long start = System.currentTimeMillis();
        try {
            Thread.sleep(random.nextInt(10000));
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        long end = System.currentTimeMillis();
        System.out.println("完成任务三,耗时:" + (end - start) + "毫秒");
    }
}

1.3 controller调用

@GetMapping("/async")
    @ResponseBody
    public Long async() throws InterruptedException {
        long start = System.currentTimeMillis();
        Thread.sleep(2000);
        myAsyncService.doTaskOne();
        myAsyncService.doTaskTwo();
        myAsyncService.doTaskThree();
        long end = System.currentTimeMillis();
        System.out.println("直接返回耗时:" + (end - start));
        return (end - start);
    }

1.4 结果分析

开始做任务一
开始做任务二
直接返回耗时:2017
开始做任务三
完成任务二,耗时:1125毫秒
完成任务一,耗时:2961毫秒
完成任务三,耗时:3155毫秒

发现其实并不是在三个任务完成之后才进行返回,而是直接返回结果,目的达到


2. 不通过接口的能不能实现@Async功能呢?

我们直接在controller里面写一个方法,并标注他是异步的,看看能不能实现?

2.1 controller实现

    @Async
    public String send() {

        long start = System.currentTimeMillis();
        for (int i = 0; i < 10; i++) {
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("第N条.........." + i);
        }
        long end = System.currentTimeMillis();
        return "10条消息发送完成" + "耗时:" + (end - start);
    }


    @GetMapping("/asyncError")
    @ResponseBody

    public Long asyncError() throws InterruptedException {

        long start = System.currentTimeMillis();
        Thread.sleep(2000);
        System.out.println(send());
        long end = System.currentTimeMillis();
        System.out.println("直接返回耗时:" + (end - start));
        return (end - start);
    }

2.2 分析结果

第N条..........0
第N条..........1
第N条..........2
第N条..........3
第N条..........4
第N条..........5
第N条..........6
第N条..........7
第N条..........8
第N条..........9
10条消息发送完成耗时:10005
直接返回耗时:12005

发现直接在controller里面写一个异步方法并不能满足需求,所以要实现异步,必须方法在一个实体类中,而且不和调用的地方处于同一个类


3. 一个service里面的方法调用其它的异步方法

3.1 修改service方法

service


public interface MyAsyncService {
    void doTaskOne();

    void doTaskTwo();

    void doTaskThree();

    void doAllTask();
}

serviceIMPL

package com.pf.org.cms.hcg.system.service.impl;

import com.pf.org.cms.hcg.system.service.MyAsyncService;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;

import java.util.Random;

@Service
public class MyAsyncImpl implements MyAsyncService {
    public static Random random = new Random();

    @Async
    @Override
    public void doTaskOne() {
        System.out.println("开始做任务一");
        long start = System.currentTimeMillis();
        try {
            Thread.sleep(random.nextInt(10000));
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        long end = System.currentTimeMillis();
        System.out.println("完成任务一,耗时:" + (end - start) + "毫秒");

    }


    @Override
    @Async
    public void doTaskTwo() {
        System.out.println("开始做任务二");
        long start = System.currentTimeMillis();
        try {
            Thread.sleep(random.nextInt(10000));
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        long end = System.currentTimeMillis();
        System.out.println("完成任务二,耗时:" + (end - start) + "毫秒");
    }

    @Override
    @Async
    public void doTaskThree() {
        System.out.println("开始做任务三");
        long start = System.currentTimeMillis();
        try {
            Thread.sleep(random.nextInt(10000));
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        long end = System.currentTimeMillis();
        System.out.println("完成任务三,耗时:" + (end - start) + "毫秒");
    }

    @Override
    public void doAllTask() {
        System.out.println("这个方法会调用三个异步方法");
        long start = System.currentTimeMillis();
        doTaskOne();
        doTaskTwo();
        doTaskThree();
        long end = System.currentTimeMillis();
        System.out.println("完成三个方法,耗时:" + (end - start) + "毫秒");
    }
}

3.2 controller完成调用

   @GetMapping("/asyncToOne")
    @ResponseBody
    public Long asyncToOne() throws InterruptedException {
        long start = System.currentTimeMillis();
        Thread.sleep(2000);
        myAsyncService.doAllTask();
        long end = System.currentTimeMillis();
        System.out.println("直接返回耗时:" + (end - start));
        return (end - start);
    }
这个方法会调用三个异步方法
开始做任务一
完成任务一,耗时:2618毫秒
开始做任务二
完成任务二,耗时:5365毫秒
开始做任务三
完成任务三,耗时:7520毫秒
完成三个方法,耗时:15503毫秒
直接返回耗时:17506

发现并没有完成异步,发现这个方法也行不通,那如果在doAllTask()上加一个异步呢?


4 在调用异步方法的方法上添加异步@Async

    @Override
    @Async
    public void doAllTask() {
        System.out.println("这个方法会调用三个异步方法");
        long start = System.currentTimeMillis();
        doTaskOne();
        doTaskTwo();
        doTaskThree();
        long end = System.currentTimeMillis();
        System.out.println("完成三个方法,耗时:" + (end - start) + "毫秒");
    }

发现居然成功了,效果如下

直接返回耗时:2013
这个方法会调用三个异步方法
开始做任务一
完成任务一,耗时:8296毫秒
开始做任务二
完成任务二,耗时:9146毫秒
开始做任务三
完成任务三,耗时:5498毫秒
完成三个方法,耗时:22940毫秒

但是要注意的是无论是否添加@Async,System.out.println("完成三个方法,耗时:" + (end - start) + "毫秒");这个都只会在这个方法的最后执行,也就是三个异步的方法结束后猜会执行,而不是直接返回

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值