web应用中实现异步任务队列
开发中遇到这样一个需求。导出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;
- }
- }