为了账号安全,请及时绑定邮箱和手机立即绑定

java后台耗时任务多线程返回结果

java后台耗时任务多线程返回结果

月关宝盒 2019-03-01 10:35:44
@RequestMapping(value = "ehr", method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON) @ResponseBody public User getUser() { User u = new User(); Future<User> future = poolTaskExecutor.submit(ehrDownloadTask); boolean flag = future.isDone(); while (!flag) { u.setMsg("未完成"); return u; } try { u = future.get(); } catch (Exception e) { e.printStackTrace(); } System.out.println("任务完成!"); return u; } 假设我我请求一个耗时任务放到线程池里执行,我想如果没执行完返回前台未完成,前台可以刷新页面显示完没完成,但是一刷新,我就又新起了一个线程去执行,所以一直返回未完成。请教下这个怎么写?
查看完整描述

2 回答

?
烙印99

TA贡献1829条经验 获得超13个赞

写个简单实现:

    private static Map<String,Future<User>> futures = new HashMap<>();
    
    @RequestMapping(value = "ehr", method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON)
    @ResponseBody
    public User getUser(HttpServletRequest request, HttpServletResponse response) {
        String sessionID = request.getSession().getId();

        User u = new User();
        u.setMsg("未完成");
        if(futures.containsKey(sessionID)) {
            Future<User> userFuture = futures.get(sessionID);
            if(userFuture.isDone()) {
                try {
                    u = userFuture.get();
                } catch (InterruptedException | ExecutionException e) {
                    e.printStackTrace();
                }
                futures.remove(sessionID);
            }
        } else {
            Future<User> future = poolTaskExecutor.submit(ehrDownloadTask);
            futures.put(sessionID,future);
        }
        return u;
    }

前台轮训直到正确返回。
Key你可以用我这样的SessionID,也可以自己根据逻辑生成
如果是分布式Tomcat可以用Redis代替HashMap

查看完整回答
反对 回复 2019-03-01
?
天涯尽头无女友

TA贡献1831条经验 获得超9个赞

需要注意一点 线程安全 HashMap不具备线程安全,这么写会出问题,建议使用ConcurrentHashMap
其次,你这个可以考虑用定时任务处理表里的记录,tableA.doneStatus这种 这个时候前端就走查询逻辑就好了,一般的业务场景还是系统自动触发处理,用户查询了你再处理,我的感觉还是不太好
以上

查看完整回答
反对 回复 2019-03-01
  • 2 回答
  • 0 关注
  • 1332 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信