springboot利用线程池异步记录日志(一)

缘由

记录日志录入数据库时,脱离主线程,实现异步插入,这样不会拖延主线程的执行时间
ps:记录日志,可以写在业务逻辑中,也可以利用aop自动记录。

	... service{
		public void login(){
			// 登录逻辑
			......
			// 记录日志插入数据库
			// 这个记录过程是要占用当前线程时间的
			// 通过异步线程执行,可以摆脱这种时间的消耗
			logService.loginInfo(userInfo);
		}
	}

步骤

1.配置线程池
2.自定义一个异步任务管理器
3.自定义任务
4.指定地点处,调用执行任务管理器,传入指定的任务

/**
* 配置线程池
* /
@Configuration
public class ThreadPoolConfig
{
	// 核心线程池大小
    private int corePoolSize = 50;
    
    /**
     * 创建线程池
     * 它继承了ThreadPoolExecutor,也就是说它也是个线程池
     * 调用它,他会去线程池中拿取一个线程来执行你装入的自定义任务
     * schedule使它能够提供一些周期任务和延迟任务相关的操作     * 
     * 相关文档
     * https://blog.csdn.net/nuannuanwfm/article/details/90573943
     */
    @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);
            }
        };
    }
}

注:存在多种不同类型的线程池。
最基础的线程池:ThreadPoolTaskExecutor
常用线程池:FixedThreadPool,CachedThreadPool,ScheduledThreadPool、SingleThreadExecutor

/**
* 自定义异步任务管理器
* /
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);
    }

    /**
     * 停止任务线程池
     */
    public void shutdown()
    {
        Threads.shutdownAndAwaitTermination(executor);
    }
}
/**
* 自定义任务
* 注意他们返回的是TimerTask,供线程池ScheduledThreadPoolExecutor调用
* /
public class AsyncFactory
{
    private static final Logger sys_user_logger = LoggerFactory.getLogger("sys-user");

    /**
     * 自定义的任务-记录登陆信息
     */
    public static TimerTask recordLogininfor(final String username, final String status, final String message,
            final Object... args)
    {
        final UserAgent userAgent = UserAgent.parseUserAgentString(ServletUtils.getRequest().getHeader("User-Agent"));
        final String ip = IpUtils.getIpAddr(ServletUtils.getRequest());
        return new TimerTask()
        {
            @Override
            public void run()
            {
                ......
                // 插入日志数据
                SpringUtils.getBean(ISysLogininforService.class).insertLogininfor(logininfor);
            }
        };
    }

    /**
     * 自定义的任务-操作日志记录
     */
    public static TimerTask recordOper(final SysOperLog operLog)
    {
        return new TimerTask()
        {
            @Override
            public void run()
            {
                // 远程查询操作地点
                operLog.setOperLocation(AddressUtils.getRealAddressByIP(operLog.getOperIp()));
                SpringUtils.getBean(ISysOperLogService.class).insertOperlog(operLog);
            }
        };
    }
}

版权声明:本文为DX_dixi原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。