天天看点

SpringBoot 项目(若依脚手架)异步操作

前言:

项目运行时出现的异常,我们需要将异常信息记录到日志,有时还需要插入数据库。

例如:项目中的用户登录模块,当用户登录系统,我们除了需要校验用户名、密码、验证码等操作外,还需要将用户登录的信息记录到日志,并且往数据库中插入一条记录。

如果采用同步操作,执行效率势必很低。建议采用异步操作。

本章节主要将 在 SpringBoot项目中 如何使用异步操作。

一、线程池配置

为什么采用线程池?

线程池 与 数据库连接池类似。 引入池的概念,主要解决效率和资源的利用率问题。当频繁创建、销毁线程会导致 效率低下,而且大量浪费内存。

线程池配置:往容器中注入异步调用线程池对象  scheduledExecutorService

package com.ruoyi.common.config.thread;

import com.ruoyi.common.utils.Threads;
import org.apache.commons.lang3.concurrent.BasicThreadFactory;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;

import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledThreadPoolExecutor;
import java.util.concurrent.ThreadPoolExecutor;

/**
 * 线程池配置
 *
 * @author ruoyi
 **/
@Configuration
public class ThreadPoolConfig {
    // 核心线程池大小
    private int corePoolSize = 50;


    /**
     * 执行周期性或定时任务
     */
    @Bean(name = "scheduledExecutorService")
    protected ScheduledExecutorService scheduledExecutorService() {
        return new ScheduledThreadPoolExecutor(corePoolSize,
                new BasicThreadFactory.Builder().namingPattern("schedule-pool-%d").daemon(true).build()) {
            @Override
            protected void afterExecute(Runnable r, Throwable t) {
                super.afterExecute(r, t);
                Threads.printException(r, t);
            }
        };
    }
}
           

二、异步任务管理器

package com.ruoyi.framework.manager;

import com.ruoyi.common.utils.spring.SpringUtils;

import java.util.TimerTask;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;

/**
 * 异步任务管理器
 *
 * @author liuhulu
 */
public class AsyncManager {
    /**
     * 操作延迟10毫秒
     */
    private final int OPERATE_DELAY_TIME = 10;

    /**
     * 异步操作任务调度线程池
     */
   private ScheduledExecutorService executor = SpringUtils.getBean("scheduledExecutorService");


    /**
     * 单例模式
     */
    private AsyncManager() {
    }

    private static AsyncManager me = new AsyncManager();

    public static AsyncManager me() {
        return me;
    }

    /**
     * 执行任务
     *
     * @param task 任务
     */
    public void execute(TimerTask task) {
        executor.schedule(task, OPERATE_DELAY_TIME, TimeUnit.MILLISECONDS);
    }
}
           

三、 测试异步调用

此处仅用于 做异步调用的测试,本来准备写测试类的,但后来发现,只有在main这个线程上,才能启动其他线程,所以如果写测试类的方法是没法 完成异步调用。 故此把测试直接写到了 application 的主类中,测试完成后删除测试部分即可

package com.ruoyi;

import com.ruoyi.framework.manager.AsyncManager;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

import java.util.TimerTask;

@SpringBootApplication
@MapperScan("com.ruoyi.**.mapper")
public class RuoyiApplication {

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

    public static void ayscTest() {
        long start = System.currentTimeMillis();
        System.out.println("AsyncManagerTest.execute()..." + Thread.currentThread().getName());
        AsyncManager.me().execute(new TimerTask() {
            @Override
            public void run() {
                System.out.println(Thread.currentThread().getName() + "start");
                try {
                    Thread.sleep(1000);
                    System.out.println(Thread.currentThread().getName() + "end");
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        });
        AsyncManager.me().execute(new TimerTask() {
            @Override
            public void run() {
                System.out.println(Thread.currentThread().getName() + "start");
                try {
                    Thread.sleep(1000);
                    System.out.println(Thread.currentThread().getName() + "end");
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        });

        long end = System.currentTimeMillis();
        System.out.println("总共耗时: " + (end - start));
    }


}
           
SpringBoot 项目(若依脚手架)异步操作

继续阅读