使用FutureTask重构现有功能

实际工作中遇到一个业务场景需要解决: 项目中需要调用外部查询服务,以验证客户某些提交数据是否满足条件。 外部服务提供方强势将查询服务封装成三个调用服务,并且需要轮训调用状态,如下图所示: 输入图片说明

最近了解到FutureTask恰恰是为了解决这种业务场景的工具,随将手头代码重构,此处只贴出重构的后的部分代码:

public class OldClientValidateTask implements Callable {

    Logger logger = LoggerFactory.getLogger(OldClientValidateTask.class);

    private volatile boolean cannotQuitJob = true;

    private boolean overtime = false;

    /**
     * 总等待超时时间
     */
    private int totalWaitMinutes = 65;

    /**
     *间隔时间
     */
    private int intvervalMinutes = 2;

    @Override
    public Object call() throws Exception {

        if (StringUtils.isBlank(oldAcctIds)) return null;

        OldClientValidateInvoker oldClientValidateInvoker = SpringContextHolder.getBean(OldClientValidateInvoker.class);

        //发送给对方请求  第一个接口
        String sendQueryResult = oldClientValidateInvoker.sendQuery(period, oldAcctIds);

        if (StringUtils.isBlank(sendQueryResult)) {
            logger.error("百度旧用户校验接口返回数据格式不正常" + sendQueryResult);
            throw new ResultNotMatchException(ErrorCodeMessageBucket.ERROR_CODE_RESULT_NOT_MATCH);

        }

        //解析出requestId
        Map<String, String> resultMap = (HashMap<String, String>) JsonMapper.fromJsonString(sendQueryResult, HashMap.class);
        String requestId = resultMap.get("data");
        if (requestId == null) return null;

        //任务启动时间
        final LocalDateTime startTime = LocalDateTime.now();

        try {
            while (cannotQuitJob) {
                //如果超时 不再调用
                if ((LocalDateTime.now().isAfter(startTime.plusMinutes(totalWaitMinutes)))) {
                    overtime = true;
                    logger.info("超时退出,超时时间:" + totalWaitMinutes);
                    break;
                }

                //第二个接口
                boolean requestSucceed = oldClientValidateInvoker.checkStatus(requestId);
                logger.info("请求调用是否成功: {}", requestSucceed);

                if (requestSucceed) {

                    //调用第三个接口 返回真正数据
                    return fetchResult(oldClientValidateInvoker, requestId);
                }

                //如果没有执行完 那么就等待
                if (cannotQuitJob) {
                    Thread.sleep(1000 * 60 * intvervalMinutes);
                }
            }

        } catch (Exception e) {
            e.printStackTrace();
        }

        return null;
    }

}

调用方过程如下:

        //创建异步调用任务
        OldClientValidateTask oldClientValidateTask = new OldClientValidateTask();
        FutureTask<List<Foo>> future = new FutureTask<List<Foo>>(oldClientValidateTask);

        // 创建线程池(使用了预定义的配置)
        ExecutorService executor = Executors.newCachedThreadPool();
        executor.execute(future);

        //查询返回结果  此处会一直等待,直到对方返回查询结果,竟然实现了异步转同步。
        List<Foo> dbdSjClientRenewInfos = future.get();

此处为一个真实的场景。FutureTask在此发挥用处。

猜你喜欢

转载自my.oschina.net/NoComments/blog/1805542