当前位置:  开发笔记 > 编程语言 > 正文

从调用方法并行执行方法

如何解决《从调用方法并行执行方法》经验,为你挑选了0个好方法。

我有一个正在使用的客户库和传入DataRequest对象拥有userid,timeout并且在它的一些其他领域.现在我使用这个DataRequest对象创建一个URL,然后我使用了一个HTTP调用RestTemplate,我的服务返回一个JSON响应,我用它来创建一个DataResponse对象并将这个DataResponse对象返回给它们.

以下是DataClient客户通过将DataRequest对象传递给我的类.DataRequest如果在getSyncData方法中花费太多时间,我正在使用客户传递的超时值来超时请求.

public class DataClient implements Client {

    private RestTemplate restTemplate = new RestTemplate();
    // first executor
    private ExecutorService service = Executors.newFixedThreadPool(15);

    @Override
    public DataResponse getSyncData(DataRequest key) {
        DataResponse response = null;
        Future responseFuture = null;

        try {
            responseFuture = getAsyncData(key);
            response = responseFuture.get(key.getTimeout(), key.getTimeoutUnit());
        } catch (TimeoutException ex) {
            response = new DataResponse(DataErrorEnum.CLIENT_TIMEOUT, DataStatusEnum.ERROR);
            responseFuture.cancel(true);
            // logging exception here               
        }

        return response;
    }   

    @Override
    public Future getAsyncData(DataRequest key) {
        DataFetcherTask task = new DataFetcherTask(key, restTemplate);
        Future future = service.submit(task);

        return future;
    }
}

DataFetcherTask 类:

public class DataFetcherTask implements Callable {

    private DataRequest key;
    private RestTemplate restTemplate;

    public DataFetcherTask(DataRequest key, RestTemplate restTemplate) {
        this.key = key;
        this.restTemplate = restTemplate;
    }

    @Override
    public DataResponse call() throws Exception {
        // In a nutshell below is what I am doing here. 
        // 1. Make an url using DataRequest key.
        // 2. And then execute the url RestTemplate.
        // 3. Make a DataResponse object and return it.

        // I am calling this whole logic in call method as LogicA
    }
}

截至目前,我的DataFetcherTask班级负责一个DataRequest密钥,如上所示..

问题陈述:-

现在我有一个小的设计变化.客户将DataRequest(例如keyA)对象传递给我的库,然后我将通过使用DataRequest(keyA)对象中存在的用户ID来对另一个服务(我在当前设计中没有做)进行新的http调用用户ID的列表,所以我将使用这些用户ID,并DataRequest为响应中返回的每个用户ID创建一个其他(keyB,keyC,keyD)对象.然后我将拥有List具有keyB,keyC和keyD DataRequest对象的对象.List将是三个中的最大元素,就是全部.

现在对于每个DataRequest对象,List我想DataFetcherTask.call并行执行上面的方法,然后List通过DataResponse为每个键添加每个.所以我将有三个并行调用DataFetcherTask.call.此并行调用背后的想法是在相同的全局超时值中获取所有这三个最大键的数据.

所以我的建议是 - DataFetcherTask类将返回List对象而不是DataResponse然后签名getSyncDatagetAsyncData方法也会改变.所以这是算法:

使用客户传递的DataRequest对象通过List调用另一个HTTP服务来进行.

对方法中的每个DataRequest进行并行调用,而不是将对象返回给客户.ListDataFetcherTask.callListDataResponse

通过这种方式,我可以在步骤1中应用相同的全局超时以及步骤2.如果上述步骤中的任何一个花费时间,我们将在getSyncData方法中超时.

DataFetcherTask 设计变更后的课程:

public class DataFetcherTask implements Callable> {

    private DataRequest key;
    private RestTemplate restTemplate;
    // second executor here
    private ExecutorService executorService = Executors.newFixedThreadPool(10);

    public DataFetcherTask(DataRequest key, RestTemplate restTemplate) {
        this.key = key;
        this.restTemplate = restTemplate;
    }

    @Override
    public List call() throws Exception {
        List keys = generateKeys();
        CompletionService comp = new ExecutorCompletionService<>(executorService);

        int count = 0;
        for (final DataRequest key : keys) {
            comp.submit(new Callable() {
                @Override
                public DataResponse call() throws Exception {
                    return performDataRequest(key);
                }
            });
        }

        List responseList = new ArrayList();
        while (count-- > 0) {
            Future future = comp.take();
            responseList.add(future.get());
        }
        return responseList;
    }

    // In this method I am making a HTTP call to another service
    // and then I will make List accordingly.
    private List generateKeys() {
        List keys = new ArrayList<>();
        // use key object which is passed in contructor to make HTTP call to another service
        // and then make List of DataRequest object and return keys.
        return keys;
    }       

    private DataResponse performDataRequest(DataRequest key) {
        // This will have all LogicA code here which is shown in my original design.
        // everything as it is same..
    }
}

现在我的问题是 -

它必须是这样的吗?解决这个问题的正确设计是什么?我的意思是让call另一种call方法的方法看起来很奇怪?

我们需要在代码中拥有两个执行器吗?有没有更好的方法来解决这个问题或我们可以在这里做的任何简化/设计变更?

我已经简化了代码,以便想法清楚我想要做什么.

推荐阅读
手机用户2402851155
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有