web应用中实现异步任务队列

时间:2024-02-17 22:16:16

开发中遇到这样一个需求。导出excel可能会超时。所以需要做成异步下载。因为下载线程会比较占用cpu资源,可能会有一些慢sql,所以需要控制并发数。

1.建立一个堵塞链表队列,用来存在任务;

2.收到用户请求创建一个下载任务,放在任务队列中。

3.在web.xml中设置一个监听类,启动一个线程定时扫描任务队列,当有任务时执行任务。

4.在执行任务时设置FutureTask超时时间,堵塞当前线程,当前任务一直不结束时,终止任务运行,释放资源。

代码:

<listener>
        <listener-class>com.taobao.kelude.k3case.listenners.ExportTaskStartupListener</listener-class>
</listener>
public class ExportTaskStartupListener implements ServletContextListener {
    @Override
    public void contextDestroyed(ServletContextEvent sce) {
        sce.getServletContext().log("定时器销毁");
    }
    @Override
    public void contextInitialized(ServletContextEvent sce) {
        sce.getServletContext().log("启动线程池");
        sce.getServletContext().log("启动定时器");
        sce.getServletContext().log("已经添加任务调度表");
        ExportTaskQueueThread exportTaskQueueThread = new ExportTaskQueueThread();
        exportTaskQueueThread.start();
    }
}

class ExportTaskQueueThread extends Thread {
    public void run() {
        System.out.println("init timer task");
        while (true) {
//            System.out.println("start timer task");
            try {
                if (!ExportTaskPoolManager.queue.isEmpty()) {
                    CallableTask callableTask = ExportTaskPoolManager.queue.take();
                    FutureTask futureTask = new FutureTask(callableTask);
                    Thread thread = new Thread(futureTask);
                    thread.start();
                    try {
                        futureTask.get(300, TimeUnit.SECONDS);
                    } catch (TimeoutException e) {
                        System.out.println("export failed for timeout");
                        futureTask.cancel(true);
                    }
                }
                Thread.sleep(10000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            } catch (ExecutionException e) {
                e.printStackTrace();
            }
        }
    }
}

 

public class ExportTaskPoolManager {
//    public static ExecutorService pool;
    public static LinkedBlockingQueue<CallableTask> queue = new LinkedBlockingQueue<CallableTask>();
}
public class ExportCaseTask extends CallableTask {
    private Logger logger = LoggerFactory.getLogger("ExportCaseTask");
    private List<Integer> priority;
    private Integer userId;
    private Boolean needFormat;
    private Integer[] suiteIds;
    private List<Integer> caseIds;
    private List<Integer> spaceIds;
    private String name;
    private String type;

    public ExportCaseTask(Integer[] suiteIds, List<Integer> caseIds, List<Integer> spaceIds, String name, List<Integer> priority, String type,boolean needFormat, Integer userId) {
        this.needFormat = needFormat;
        this.priority = priority;
        this.userId = userId;
        this.suiteIds = suiteIds;
        this.caseIds = caseIds;
        this.spaceIds = spaceIds;
        this.name = name;
        this.type = type;
    }

    private TestCaseService testCaseService = (TestCaseService) SpringContextUtils.getBean("testCaseService");

    public Object call() throws Exception {

        try {
            testCaseService.generateASync(suiteIds, caseIds, spaceIds, name, priority, type, needFormat, userId);
            logger.info("generateASync ok");
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
        }
        return 1;
    }
}