Spring中@Async用法详解及简单实例

yizhihongxing

当我们需要在Spring应用中增加异步任务支持时,可以使用@Async注解来标示异步方法。@Async注解可以标识在任何方法上面,表示该方法会异步执行。本篇攻略将从以下几个方面介绍Spring中@Async的用法,包括:

  1. 开启异步支持
  2. 使用@Async注解实现异步方法
  3. 使用Future返回异步结果
  4. 示例1:异步方法的实现
  5. 示例2:带参数的异步方法

开启异步支持

首先,我们需要在Spring应用中开启异步支持。在XML配置中,可以通过在中添加元素来开启异步支持。

<task:annotation-driven>
    <task:executor id="myThreadPoolExecutor" pool-size="5"/>
    <task:executor id="secondThreadPoolExecutor" pool-size="10"/>
    <task:executor id="customAsyncExecutor" pool-size="20"/>
    <task:async-method-executor task-executor="customAsyncExecutor"/>
    <async/>
</task:annotation-driven>

Java Config中,可以通过使用@EnableAsync注解开启异步支持。

@Configuration
@EnableAsync
public class AppConfig {
    //其他配置
}

使用@Async注解实现异步方法

有了异步支持后,我们就可以在方法上添加@Async注解来实现异步方法。@Async注解发挥作用的前提是方法必须是public类型方法。

@Service
public class UserService{

    @Async
    public void longTimeOper(){
        //xxxxxx
    }
    //其他代码
}

使用Future返回异步结果

如果需要获取异步方法的返回结果,可以在方法的返回类型上使用Java的Future类型。

@Service
public class UserService{

    @Async
    public Future<String> longTimeOperWithResult(){
        //xxxxxx
        return new AsyncResult<String>("result");
    }
    //其他代码
}

示例1:异步方法的实现

假设我们需要批量处理用户信息,并返回处理成功的用户数。首先,我们定义一个UserService:

@Service
public class UserService {

    private static final Logger log = LoggerFactory.getLogger(UserService.class);

    private static final Random random= new Random();

    public int batchSaveUserList(List<User> users) throws InterruptedException {
        for (User user : users) {
            saveUser(user);
        }
        Thread.sleep(5000);//模拟保存数据需要5秒
        return users.size();
    }

    @Async
    public Future<Integer> batchSaveUserListAsync(List<User> users) throws InterruptedException {
        return new AsyncResult<>(batchSaveUserList(users));
    }

    public void saveUser(User user) throws InterruptedException {
        log.info("save user: {}", user);
        Thread.sleep(random.nextInt(1000));
    }
}

UserService中包含了两个方法batchSaveUserList和batchSaveUserListAsync,前者是同步方法,后者是异步方法。batchSaveUserList方法模拟需要花费5秒的数据保存操作,而saveUser方法模拟插入单个用户时的操作。

接下来,我们编写测试代码:

@RunWith(SpringRunner.class)
@SpringBootTest(classes = Application.class)
public class UserServiceTest {

    private static final Logger log = LoggerFactory.getLogger(UserServiceTest.class);

    @Autowired
    private UserService userService;

    @Test
    public void batchSaveUserTest() throws InterruptedException {
        List<User> users = new ArrayList<>(10);
        for (int i = 0; i < 10; i++) {
            User user = new User();
            user.setName("name_" + i);
            user.setAge(20 + i);
            users.add(user);
        }
        int size = userService.batchSaveUserList(users);
        log.info("batchSaveUserList saved: {} records", size);
    }

    @Test
    public void batchSaveUserAsyncTest() throws InterruptedException, ExecutionException {
        List<User> users = new ArrayList<>(10);
        for (int i = 0; i < 10; i++) {
            User user = new User();
            user.setName("name_" + i);
            user.setAge(20 + i);
            users.add(user);
        }
        Future<Integer> future = userService.batchSaveUserListAsync(users);
        int size = future.get();
        log.info("batchSaveUserAsync saved: {} records", size);
    }
}

在测试代码中,我们分别调用了同步方法batchSaveUserList和异步方法batchSaveUserListAsync。执行结果表明异步方法可以提前返回,不必等到数据保存完成。

示例2:带参数的异步方法

为了更好地说明带参数的异步方法,我们假设初始化一个User对象需要5秒。此时,我们就可以使用异步方法initUser来异步初始化一个User对象:

@Service
public class UserService {

    private static final Logger log = LoggerFactory.getLogger(UserService.class);

    private static final Random random= new Random();

    public User initUser() throws InterruptedException {
        Thread.sleep(5000);//模拟初始化User需要5秒
        User user = new User();
        user.setName("user");
        user.setAge(18);
        return user;
    }

    @Async
    public Future<User> initUserAsync() throws InterruptedException {
        User user = initUser();
        return new AsyncResult<>(user);
    }

    public void saveUser(User user) throws InterruptedException {
        log.info("save user: {}", user);
        Thread.sleep(random.nextInt(1000));
    }
}

使用方式如下:

@RunWith(SpringRunner.class)
@SpringBootTest(classes = Application.class)
public class UserServiceTest {

    private static final Logger log = LoggerFactory.getLogger(UserServiceTest.class);

    @Autowired
    private UserService userService;

    @Test
    public void initUserTest() throws InterruptedException {
        User user = userService.initUser();
        userService.saveUser(user);
    }

    @Test
    public void initUserAsyncTest() throws ExecutionException, InterruptedException {
        Future<User> future = userService.initUserAsync();
        User user = future.get();
        userService.saveUser(user);
    }
}

执行结果表明异步方法可以提前返回,不必等到User对象初始化完成。

至此,我们已经对Spring中的@Async用法进行了详细的讲解,并提供了两个实际应用的示例,相信能够帮助读者更好地理解和使用@Async注解。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:Spring中@Async用法详解及简单实例 - Python技术站

(0)
上一篇 2023年5月19日
下一篇 2023年5月19日

相关文章

  • 使用JAVA实现http通信详解

    使用JAVA实现http通信可以通过以下几个步骤完成: 步骤1:引入相关包 在实现http通信之前,需要引入相关的包,这些包中包含了实现http通信所需要的类和方法。Java中实现http通信一般使用Apache提供的HttpComponents包,该包可以通过Maven引入,如下: <dependency> <groupId>org…

    Java 2023年5月18日
    00
  • jQuery解析XML文件同时动态增加js文件的方法

    首先需要明确的是,jQuery提供了内置的函数来实现解析XML文件和动态增加js文件。下面是详细的操作步骤。 解析XML文件 步骤一:通过ajax方法获取XML数据 使用jQuery的ajax方法,通过URL链接获取XML数据。使用ajax方法时,需要设置dataType为xml。 $.ajax({ url: ‘xml/your_xml_file.xml’,…

    Java 2023年6月15日
    00
  • Java基础学习笔记之数组详解

    Java基础学习笔记之数组详解 什么是数组? 数组是Java中最常用的数据结构之一,它是一组相同类型的数据的有序集合,每个数据被称为一个数组元素。是一维数组或多维数组(嵌套数组)。 如何定义数组? 定义数组的语法如下: 数据类型[] 数组名称 = new 数据类型[数组长度]; 其中, 数据类型是指数组中存储元素的类型,数组名称是取自己喜欢的名称,数组长度是…

    Java 2023年5月26日
    00
  • Java中的封装是什么?

    Java中的封装(Encapsulation)是一种面向对象编程(OOP)中常见的原则之一,它是OOP中三大特征(封装、继承和多态)之一。 封装是指将一个对象的属性和方法进行私有化,使其不被外部直接访问和修改。目的在于隐藏对象的具体实现细节,增加代码的可读性、可维护性和安全性。在Java中,使用关键字private来实现封装。 下面以一个银行账户类Accou…

    Java 2023年4月27日
    00
  • JAVA各种OOM代码示例与解决方法

    “JAVA各种OOM代码示例与解决方法”攻略 什么是OOM OOM是”Out Of Memory”的缩写,意为内存用尽。Java程序中,如果申请内存超过了JVM所限制的最大内存,则会发生OOM异常。在Java程序中,由于内存泄漏或者分配内存过多导致的OOM异常较为常见。 OOM异常的种类 Java heap spaceJVM使用的java堆内存中没有多余的空…

    Java 2023年5月20日
    00
  • java定时任务的实现方法

    下面是针对”Java定时任务的实现方法”的详细攻略,主要介绍如何使用Java实现定时任务。 什么是定时任务? 定时任务是指在预定时期或时间,按照一定轨迹执行一些预定的操作或服务。 Java中实现定时任务的方法 1. Timer类 Java中提供了java.util.Timer类,它可以帮助我们实现简单的定时任务。 public class TimerTask…

    Java 2023年5月20日
    00
  • 全面解析Spring Security 过滤器链的机制和特性

    全面解析Spring Security 过滤器链的机制和特性 什么是Spring Security过滤器链? Spring Security过滤器链是Spring Security处理HTTP请求的核心组件之一。在Spring Security框架中,每一个安全的URL请求都需要通过一系列的过滤器组成的过滤器链来进行权限的校验和身份认证,该过滤器链是有顺序的…

    Java 2023年5月20日
    00
  • Java实现中文算数验证码的实现示例(算数运算+-*/)

    下面我来为你详细讲解Java实现中文算数验证码的完整攻略。 思路 实现中文算数验证码,思路如下: 生成指定位数(如四位)的随机算式和结果; 将随机数字与其对应的中文词组成一个map,以便后面进行替换; 将算式中的数字替换为对应的中文; 将结果数字同样替换为对应的中文; 将算式和结果拼接成字符串,并返回到前端展示。 示例 下面是Java实现中文算数验证码的示例…

    Java 2023年5月20日
    00
合作推广
合作推广
分享本页
返回顶部