Spring系列第37篇:@EnableAsync & @Async 实现方法异步调用

来个spring配置类,需要加上@EnableAsync开启bean方法的异步调用.

package com.javacode2018.async.demo1;

import org.springframework.context.annotation.ComponentScan;

import org.springframework.context.annotation.EnableAspectJAutoProxy;

import org.springframework.scheduling.annotation.EnableAsync;

@ComponentScan

@EnableAsync

public class MainConfig1 {

}

测试代码

package com.javacode2018.async;

import com.javacode2018.async.demo1.LogService;

import com.javacode2018.async.demo1.MainConfig1;

import org.junit.Test;

import org.springframework.context.annotation.AnnotationConfigApplicationContext;

import java.util.concurrent.TimeUnit;

public class AsyncTest {

@Test

public void test1() throws InterruptedException {

AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();

context.register(MainConfig1.class);

context.refresh();

LogService logService = context.getBean(LogService.class);

System.out.println(Thread.currentThread() + " logService.log start," + System.currentTimeMillis());

logService.log(“异步执行方法!”);

System.out.println(Thread.currentThread() + " logService.log end," + System.currentTimeMillis());

//休眠一下,防止@Test退出

TimeUnit.SECONDS.sleep(3);

}

}

运行输出

Thread[main,5,main] logService.log start,1595223990417

Thread[main,5,main] logService.log end,1595223990432

Thread[SimpleAsyncTaskExecutor-1,5,main]开始记录日志,1595223990443

Thread[SimpleAsyncTaskExecutor-1,5,main]日志记录完毕,1595223992443

前2行输出,可以看出logService.log立即就返回了,后面2行来自于log方法,相差2秒左右。

前面2行在主线程中执行,后面2行在异步线程中执行。

5、获取异步返回值


用法

若需取异步执行结果,方法返回值必须为Future类型,使用spring提供的静态方法org.springframework.scheduling.annotation.AsyncResult#forValue创建返回值,如:

public Future getGoodsInfo(long goodsId) throws InterruptedException {

return AsyncResult.forValue(String.format(“商品%s基本信息!”, goodsId));

}

案例

场景:电商中商品详情页通常会有很多信息:商品基本信息、商品描述信息、商品评论信息,通过3个方法来或者这几个信息。

这3个方法之间无关联,所以可以采用异步的方式并行获取,提升效率。

下面是商品服务,内部3个方法都需要异步,所以直接在类上使用@Async标注了,每个方法内部休眠500毫秒,模拟一下耗时操作。

package com.javacode2018.async.demo2;

import org.springframework.scheduling.annotation.Async;

import org.springframework.scheduling.annotation.AsyncResult;

import org.springframework.stereotype.Component;

import java.util.Arrays;

import java.util.List;

import java.util.concurrent.Future;

import java.util.concurrent.TimeUnit;

@Async

@Component

public class GoodsService {

//模拟获取商品基本信息,内部耗时500毫秒

public Future getGoodsInfo(long goodsId) throws InterruptedException {

TimeUnit.MILLISECONDS.sleep(500);

return AsyncResult.forValue(String.format(“商品%s基本信息!”, goodsId));

}

//模拟获取商品描述信息,内部耗时500毫秒

public Future getGoodsDesc(long goodsId) throws InterruptedException {

TimeUnit.MILLISECONDS.sleep(500);

return AsyncResult.forValue(String.format(“商品%s描述信息!”, goodsId));

}

//模拟获取商品评论信息列表,内部耗时500毫秒

public Future<List> getGoodsComments(long goodsId) throws InterruptedException {

TimeUnit.MILLISECONDS.sleep(500);

List comments = Arrays.asList(“评论1”, “评论2”);

return AsyncResult.forValue(comments);

}

}

来个spring配置类,需要加上@EnableAsync开启bean方法的异步调用.

package com.javacode2018.async.demo2;

import org.springframework.context.annotation.ComponentScan;

import org.springframework.scheduling.annotation.EnableAsync;

@ComponentScan

@EnableAsync

public class MainConfig2 {

}

测试代码

@Test

public void test2() throws InterruptedException, ExecutionException {

AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();

context.register(MainConfig2.class);

context.refresh();

GoodsService goodsService = context.getBean(GoodsService.class);

long starTime = System.currentTimeMillis();

System.out.println(“开始获取商品的各种信息”);

long goodsId = 1L;

Future goodsInfoFuture = goodsService.getGoodsInfo(goodsId);

Future goodsDesc

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值