越写悦快乐之Spring Boot项目如何使用定时任务

2019-12-14  本文已影响0人  韬声依旧在路上
Spring项目 - 图片来自简书App

今天的越写悦快乐系列文章为大家带来工作上的那些事儿,大家都知道在Spring Boot 项目中,我们经常需要定时地执行一些重复性的任务,比如统计用户访问日志,数据库的定时备份,那么这些业务都需要定时任务来为我们提供API,接下来我为大家分享一下如何在Spring Boot项目中接入定时任务。

开发环境

Maven 版本

distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.6.0/apache-maven-3.6.0-bin.zip

Build 版本

<plugin>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-maven-plugin</artifactId>
    <version>2.2.1.RELEASE</version>
</plugin>

构建步骤

添加依赖

对于Spring Boot的项目我们只需要在POM文件的parent标签中加入以下内容即可。

<parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>2.2.1.RELEASE</version>
    <relativePath/>
</parent>

配置Task

我们在application.properties文件中加入以下内容:

spring.task.execution.pool.max-size=16
spring.task.execution.pool.core-size=16
spring.task.execution.pool.keep-alive=10s
spring.task.execution.pool.queue-capacity=100
spring.task.execution.pool.allow-core-thread-timeout=true
spring.task.execution.thread-name-prefix=async-tour-

启用注解

我们在AsyncTourApplication中加入@EnableAsync注解,告知Spring框架开启任务。

package me.weitao.app;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.scheduling.annotation.EnableAsync;

/**
 * @author Watony Weng
 * @date 2019/12/03
 */

@EnableAsync
@SpringBootApplication
public class AsyncTourApplication {

    public static void main(String[] args) {
        SpringApplication.run(AsyncTourApplication.class, args);
    }

}

编写任务类

为了方便测试,我们模拟线程执行并在执行过程中等待数秒,可以使用@Async应用到某个方法上,表明该方法支持异步,文件内容请参考:

package me.weitao.app.components;

import lombok.extern.slf4j.Slf4j;
import org.springframework.scheduling.annotation.Async;
import org.springframework.scheduling.annotation.AsyncResult;
import org.springframework.stereotype.Component;

import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;

/**
 * @author Zhuye
 * @date 2019/12/05
 */

@Component
@Slf4j
public class SimulationTask {

    /**
     * 模拟5秒的异步任务
     */
    @Async
    public Future<Boolean> asyncTask1() throws InterruptedException {
        doTask("asyncTask1", 5);
        return new AsyncResult<>(Boolean.TRUE);
    }

    /**
     * 模拟2秒的异步任务
     */
    @Async
    public Future<Boolean> asyncTask2() throws InterruptedException {
        doTask("asyncTask2", 2);
        return new AsyncResult<>(Boolean.TRUE);
    }

    /**
     * 模拟3秒的异步任务
     */
    @Async
    public Future<Boolean> asyncTask3() throws InterruptedException {
        doTask("asyncTask3", 3);
        return new AsyncResult<>(Boolean.TRUE);
    }

    /**
     * 模拟5秒的同步任务
     */
    public void task1() throws InterruptedException {
        doTask("task1", 5);
    }

    /**
     * 模拟2秒的同步任务
     */
    public void task2() throws InterruptedException {
        doTask("task2", 2);
    }

    /**
     * 模拟3秒的同步任务
     */
    public void task3() throws InterruptedException {
        doTask("task3", 3);
    }

    private void doTask(String taskName, Integer time) throws InterruptedException {
        log.info("{}开始执行,当前线程名称【{}】", taskName, Thread.currentThread().getName());
        TimeUnit.SECONDS.sleep(time);
        log.info("{}执行成功,当前线程名称【{}】", taskName, Thread.currentThread().getName());
    }

}

编写测试类

我们在test/java下创建SimulationTaskTest类,在该类中注入SimulationTask,参考的文件的文件内容如下:

package me.weitao.app.task;

import lombok.extern.slf4j.Slf4j;

import me.weitao.app.AsyncTourApplicationTests;
import me.weitao.app.components.SimulationTask;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;

import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;

/**
 * @author Zhuye
 * @date 2019/12/03
 */

@Slf4j
public class SimulationTaskTest extends AsyncTourApplicationTests {

    @Autowired
    private SimulationTask task;

    /**
     * 测试异步任务
     */
    @Test
    public void asyncTaskTest() throws InterruptedException, ExecutionException {
        long start = System.currentTimeMillis();
        Future<Boolean> asyncTask1 = task.asyncTask1();
        Future<Boolean> asyncTask2 = task.asyncTask2();
        Future<Boolean> asyncTask3 = task.asyncTask3();

        asyncTask1.get();
        asyncTask2.get();
        asyncTask3.get();
        long end = System.currentTimeMillis();
        log.info("异步任务全部执行结束,总耗时:{} 毫秒", (end - start));
    }

    /**
     * 测试同步任务
     */
    @Test
    public void taskTest() throws InterruptedException {
        long start = System.currentTimeMillis();
        task.task1();
        task.task2();
        task.task3();
        long end = System.currentTimeMillis();
        log.info("同步任务全部执行结束,总耗时:{} 毫秒", (end - start));
    }

}

运行测试查看结果

测试类编写完成后,我们可以定位到该测试类,点击方法前面的三角即可执行该测试方法,下面的截图就是异步方法的执行结果。

运行结果 - 图片来自简书App

个人感想及收获

通过以上知识点的梳理,我们了解了如何利用注解快速执行定时任务,提升我们的业务服务能力,构建合适的产品矩阵,通过注解结合Spring框架强大的依赖注入特性可以构建高并发的Web应用,我们不仅要知道底层的技术细节,更要从整体出发、梳理系统架构、完善技术盲点、扩展技术边界、让技术能更好地服务于业务,要让业务能强化技术的潜能,我相信这不是一朝一夕的事情,需要我们去梳理、完善、成就和总结技术要点,让我们一起为公司创造更大的价值。若是我的文章对你有所启发,那将是我莫大的荣幸。

上一篇下一篇

猜你喜欢

热点阅读