原创

Java异步任务管理器

温馨提示:
本文最后更新于 2022年06月11日,已超过 115 天没有更新。若文章内的图片失效(无法正常加载),请留言反馈或直接联系我

1. 什么是异步任务管理器

异步任务管理器就是一个可以快速创建异步任务的一个工具

2. 为什么要采用异步任务

提高业务系统响应速度,实现不同业务之间的解耦

2.1 举例

|记录访客日志,发送工单等
如果系统每一步的日志记录都是伴随着业务一起执行的,那么当系统访问量增的时候,就会大大降低系统的响应速度
|因为写操作是比读操作更耗时的,如果能够做到异步的记录日志,就不必等待日志记录完成即可返回查询、搜索结果,

3. 如何实现异步任务管理器

异步任务可以通过多线程也可以通过消息队列配合定时任务来实现,但是相对于小型系统采用多线程的方式相对便捷

3.1 多线程实现异步任务

3.1.1 自定义线程池

自定义线程池实现了单例模式获取自定义线程池对象,以及通过该单例对象初始化一个线程池对象executor

MyThreadPool.java

package com.zyd.blog.framework.config;

import lombok.Data;
import org.apache.commons.lang3.concurrent.BasicThreadFactory;

import java.util.concurrent.*;

/**
 * @Auth: cxc
 * @DATE: 2022-6-10
 * 自定义线程池
 */
@Data
public class MyThreadPool {

    // 自定义的线程池单例对象
    private static MyThreadPool myThreadPool;

    // 核心线程池大小
    private static int corePoolSize = 2;

    // 最大可创建的线程数
    private static int maxPoolSize = 3;

    // 队列最大长度
    private static int queueCapacity = 1000;

    // 线程池维护线程所允许的空闲时间
    private static int keepAliveSeconds = 300;

    // 线程池所需要一个队列来存放线程对象
    private static BlockingQueue blockingQueue = new LinkedBlockingDeque(queueCapacity);

    // 线程池中创建线程的名称
    private String threadName;

    // 真正的线程池对象
    private ThreadPoolExecutor executor;

    public MyThreadPool() {

    }

    /**
     * 获取自定义线程池单例对象
     * @param threadName
     * @return
     */
    public static MyThreadPool getInstance(String threadName) {
        if (myThreadPool != null && threadName.equals(myThreadPool.threadName)) {
            return myThreadPool;
        }
        synchronized (MyThreadPool.class) {
            myThreadPool = new MyThreadPool();
            myThreadPool.setThreadName(threadName);
            myThreadPool.setExecutor(new ThreadPoolExecutor(corePoolSize,maxPoolSize,keepAliveSeconds, TimeUnit.SECONDS,blockingQueue,
                    new BasicThreadFactory.Builder().namingPattern(threadName+"-%d").daemon(true).build(),
                    new ThreadPoolExecutor.CallerRunsPolicy()));
        }
        return myThreadPool;
    }

}

3.1.1 异步任务管理器

执行异步任务execute()方法
停止线程池shutdown()方法

AsyncTaskManager.jva

package com.zyd.blog.util;


import com.zyd.blog.framework.config.MyThreadPool;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;

import java.util.TimerTask;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

/**
 * @Auth: cxc
 * @DATE: 2022-6-10
 * 异步任务管理器,用于异步任务的执行
 */
@Slf4j
@Data
@Component
public class AsyncTaskManager {



    // 单例模式生成异步任务管理器对象
    private static AsyncTaskManager asyncTaskManager;

    // 操作延迟10毫秒
    private final int START_DELAY_TIME = 10;

    // 获取线程池对象
    private ThreadPoolExecutor executor;

    private String threadName;


    /**
     * 获取异步任务单例对象
     * 用于执行异步任务
     * @return
     */
    public static AsyncTaskManager getInstance(String threadName) {
        if (null != asyncTaskManager && threadName.equals(asyncTaskManager.getThreadName())) {
            return asyncTaskManager;
        }
        synchronized (AsyncTaskManager.class) {
            asyncTaskManager = new AsyncTaskManager();
            asyncTaskManager.setThreadName(threadName);
            asyncTaskManager.setExecutor(MyThreadPool.getInstance(threadName).getExecutor());
        }
        return asyncTaskManager;
    }

    /**
     * 执行异步任务
     * @param task
     */
    public void execute(TimerTask task) {
        if (executor ==null) {
            executor = MyThreadPool.getInstance("threadName").getExecutor();
        }
        executor.execute(task);
    }

    /**
     * 停止任务线程池
     */
    public void shutdown() {

        if (executor != null && !executor.isShutdown())
        {
            executor.shutdown();
            try
            {
                if (!executor.awaitTermination(120, TimeUnit.SECONDS))
                {
                    executor.shutdownNow();
                    if (!executor.awaitTermination(120, TimeUnit.SECONDS))
                    {
                        log.info("Pool did not terminate");
                    }
                }
            }
            catch (InterruptedException ie)
            {
                executor.shutdownNow();
                Thread.currentThread().interrupt();
            }
        }
    }
}

3.1.3 异步工厂

用于定义各种异步任务

AsyncFactory.java

package com.zyd.blog.util;

import lombok.extern.slf4j.Slf4j;

import java.util.TimerTask;

/**
 * @Auth: cxc
 * @DATE: 2022-6-11
 */
@Slf4j
public class AsyncFactory {
    public static TimerTask insertSerachRecord(String name,String result) {
        return new TimerTask() {
            @Override
            public void run() {
                log.info("{}搜索了{}",name,result);
            }
        };
    }
    public static TimerTask writerLog(String name,String result) {
        return new TimerTask() {
            @Override
            public void run() {
                log.info("{}访问了{}",name,result);
            }
        };
    }

}

3.1.4 测试

CommonTest.java

package com.zyd.blog;

import com.zyd.blog.util.AsyncFactory;
import com.zyd.blog.util.AsyncTaskManager;

import java.util.TimerTask;
import java.util.concurrent.ThreadPoolExecutor;

/**
 * @Auth: cxc
 * @DATE: 2022-6-11
 */
public class CommonTest {
    public static void main(String[] args) throws InterruptedException {
        AsyncTaskManager.getInstance("记录日志").execute(AsyncFactory.insertSerachRecord("杨幂","我的博客"));
        AsyncTaskManager.getInstance("搜索记录").execute(AsyncFactory.insertSerachRecord("杨幂","小陈没烦恼"));
        AsyncTaskManager.getInstance("记录日志").execute(AsyncFactory.insertSerachRecord("柳岩","主页"));
        AsyncTaskManager.getInstance("记录日志").execute(AsyncFactory.insertSerachRecord("柳岩","我爱你"));




        Thread.sleep(10000);
        System.out.println("主线程结束!");

    }
}

3.1.5 运行结果

file

正文到此结束
本文目录