Refactoring existing features with FutureTask

In actual work, a business scenario needs to be solved: An external query service needs to be called in the project to verify that some of the customer's submitted data meets the criteria. The external service provider has a strong tendency to encapsulate the query service into three call services, and needs to rotate the training call status, as shown in the following figure: .

Recently, I learned that FutureTask is just a tool to solve this business scenario. With the reconstruction of the code at hand, only part of the code after the reconstruction is posted here:

public class OldClientValidateTask implements Callable {

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

    private volatile boolean cannotQuitJob = true;

    private boolean overtime = false;

     * Total wait timeout
    private int totalWaitMinutes = 65;

     *Interval time
    private int intvervalMinutes = 2;

    public Object call() throws Exception {

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

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

        //Send request to the first interface
        String sendQueryResult = oldClientValidateInvoker.sendQuery(period, oldAcctIds);

        if (StringUtils.isBlank(sendQueryResult)) {
            logger.error("Data format returned from Baidu old user verification interface is abnormal" + sendQueryResult);
            throw new ResultNotMatchException(ErrorCodeMessageBucket.ERROR_CODE_RESULT_NOT_MATCH);


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

        //Task start time
        final LocalDateTime startTime =;

        try {
            while (cannotQuitJob) {
                //No more calls if timeout
                if (( {
                    overtime = true;
          "Overtime exit,Timeout time:" + totalWaitMinutes);

                //Second interface
                boolean requestSucceed = oldClientValidateInvoker.checkStatus(requestId);
      "Whether the request call is successful: {}", requestSucceed);

                if (requestSucceed) {

                    //Call the third interface to return real data
                    return fetchResult(oldClientValidateInvoker, requestId);

                //If not, wait
                if (cannotQuitJob) {
                    Thread.sleep(1000 * 60 * intvervalMinutes);

        } catch (Exception e) {

        return null;


The caller's procedure is as follows:

        //Create asynchronous call task
        OldClientValidateTask oldClientValidateTask = new OldClientValidateTask();
        FutureTask<List<Foo>> future = new FutureTask<List<Foo>>(oldClientValidateTask);

        // Create thread pool (using predefined configuration)
        ExecutorService executor = Executors.newCachedThreadPool();

        //The query return result will wait here until the other party returns the query result, and asynchronous synchronization is realized.
        List<Foo> dbdSjClientRenewInfos = future.get();

This is a real scene. FutureTask is useful here.

Posted by IWS on Thu, 26 Mar 2020 10:18:11 -0700