Springboot 构建异步TaskManager的优雅处理线程任务

本文介绍了如何使用Java创建一个单例的DataSyncTaskManager类,通过ThreadPoolExecutor实现线程池管理和异步任务提交。Task对象作为运行实体,Service启动时启动TaskManager线程,后续业务只需提交任务即可执行。
摘要由CSDN通过智能技术生成
  1. 首先定义一个TaskManager管理类

import lombok.extern.slf4j.Slf4j;

import java.util.concurrent.BlockingQueue;
import java.util.concurrent.Executors;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;

@Slf4j
public class DataSyncTaskManager {
    private static DataSyncTaskManager taskManager = null;
    private static BlockingQueue<Runnable> taskQueue = new LinkedBlockingQueue<>();

    private ThreadPoolExecutor taskExecutorPool;

    private DataSyncTaskManager() {
        XXXConfig xxxConfig = SpringContextUtil.getBean(XXXConfig.class);
        this.taskExecutorPool = (ThreadPoolExecutor) Executors.newFixedThreadPool(xxxConfig .getDataSyncThreadNum());
    }

    /**
     * 构建唯一Manager对象单例
     *
     * @return
     */
    public static synchronized DataSyncTaskManager getManager() {
        if (null == taskManager) {
            taskManager = new DataSyncTaskManager();
        }
        return taskManager;
    }

    /**
     * 提交需要运行的任务
     * @param task
     */
    public void submitTask(DataSyncTask task) {
        taskQueue.add(task);
        log.info("[DataSyncTaskManager] submitTask size={}", taskQueue.size());
    }

    public void runTaskDaemon(){
        log.info("[DataSyncTaskManager] runTaskDaemon start");
        Thread thread = new Thread(() -> {
            while (true) {
                try {
                    Runnable task = taskQueue.take();
                    taskExecutorPool.submit(task);
                    log.info("[DataSyncTaskManager] runTaskDaemon submit task={}", task);
                    Thread.sleep(3000);
                } catch (Exception e) {
                    log.error("[startTaskRunningDaemon] task run error", e);
                }
            }
        });
        thread.start();
    }
}

  1. 构建一个Task对象,作为线程池的运行实体,由Manager进行管理

import lombok.Data;
import lombok.extern.slf4j.Slf4j;

import java.io.PrintWriter;
import java.io.StringWriter;


@Data
@Slf4j
public class DataSyncTask implements Runnable{
    private String stuid;
    private String displayId;

    public DataSyncTask(String stuid, String displayId) {
        this.stuid = stuid;
        this.displayId = displayId;
    }

    /**
     * When an object implementing interface <code>Runnable</code> is used
     * to create a thread, starting the thread causes the object's
     * <code>run</code> method to be called in that separately executing
     * thread.
     * <p>
     * The general contract of the method <code>run</code> is that it may
     * take any action whatsoever.
     *
     * @see Thread#run()
     */
    @Override
    public void run() {
        log.info("[DataSyncTask] run task start, stuid={}, displayId={}", stuid, displayId);
        DataSyncComponent syncComponent = SpringContextUtil.getBean(DataSyncComponent.class);
        try {
            syncComponent.syncData(stuid, displayId);
        }catch (Exception e){
            log.error("[DataSyncTask] error", e);
        }

        log.info("[DataSyncTask] run task end, stuid={}, displayId={}", stuid, displayId);
    }

    public static String getStackTrace(Exception e){
        StringWriter stringWriter = new StringWriter();
        PrintWriter printWriter = new PrintWriter(stringWriter);
        e.printStackTrace(printWriter);
        printWriter.close();

        try {
            stringWriter.close();
        }catch (Exception e1){
            log.error("[getStackTrace] failed", e1);
        }

        return stringWriter.toString();
    }
}
  1. 核心的业务处理对象
import javax.annotation.Resource;
import java.io.File;
import java.time.LocalDateTime;
import java.util.HashMap;
import java.util.Map;

@Slf4j
@Component
public class DataSyncComponent {
    @Resource
    XXXMapper xxxMapper;
    
    @Resource
    RedisUtils redisUtils;


    public void syncData(String stuid, String displayId){
        log.info("[do something]");
    }
}

  1. 服务启动的时候,启动taskManager线程
@Slf4j
@Component
public class DataSyncRunner implements ApplicationRunner {

    /**
     * Callback used to run the bean.
     *
     * @param args incoming application arguments
     * @throws Exception on error
     */
    @Override
    public void run(ApplicationArguments args) throws Exception {
        //运行任务执行器
        DataSyncTaskManager dataSyncTaskManager = DataSyncTaskManager.getManager();
        dataSyncTaskManager.runTaskDaemon();
    }
}
  1. 后续的业务只需要触发新增提交task即可自动执行异步任务
DataSyncTask dataSyncTask = new DataSyncTask(stuid, displayId);
DataSyncTaskManager.getManager().submitTask(dataSyncTask);
  1. 其他:手动获取bean的对象类

@Component
public class SpringContextUtil implements ApplicationContextAware {
    private static ApplicationContext applicationContext;

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        SpringContextUtil.applicationContext = applicationContext;
    }

    public static ApplicationContext getApplicationContext() {
        return applicationContext;
    }

    public static <T> T getBean(Class<T> clazz) {
        return getApplicationContext().getBean(clazz);
    }

    public static <T> T getBean(String name, Class<T> clazz) {
        return getApplicationContext().getBean(name, clazz);
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值