部分检索一批任务中的数据

时间:2018-04-25 13:28:53

标签: java multithreading concurrency executorservice callable

我正在使用 ExecutorService 来提交一批任务。我这样做是这样的:

ListeningExecutorService exec = MoreExecutors.listeningDecorator(Executors.newFixedThreadPool(threads));
List<ListenableFuture<Whatever>> futures = new ArrayList<>();
for (int i = 0; i < 100; i++) {
  results.add(exec.submit(new MyTask(i)));
}

ListenableFuture<List<Whatever>> listListenableFuture = Futures.successfulAsList(futures);

try {
    List<Whatever> responses = listListenableFuture.get(2000, TimeUnit.MILLISECONDS);
    for (Whatever response : responses) {
      LOG.info("Yay!");
    }
} catch (TimeoutException e) {
  LOG.info("Timeout Exception");
} catch (Exception e) {
  // Nay! 
}

这里的问题是 - 如果其中一个任务花费的时间超过2000毫秒,则抛出TimeoutException并且我在响应中什么也得不到,尽管某些任务可能已经完成了。

所以我想检索已经完成的任务的响应(部分或完整),直到超时(2000ms)。例如:

  

(相对于批次调用的START_TIME的时间)   
任务-1:1000ms   
任务-2: 3000ms   
任务-3:1800ms

     


输出:   
超时例外

     


期望输出:   
耶! &lt; - 对应于任务-1   
耶! &lt; - 对应于task-3

我想到的一个解决方案是单独获取期货并将其超时设置为MAX(0, TIME_OUT - TIME_NOW - START_TIME)。这可能有用,但对我来说似乎不是一个干净的解决方案。

2 个答案:

答案 0 :(得分:0)

您可以使用decorate callable来处理超时。

假设这是原始的可调用:

class OriginalCallable implements Callable<String> {
    @Override
    public String call() throws Exception {
        return "";
    }
}

你可以用这个原始的callable和执行者构建一个可调用的decolable:

class DecorateCallable implements Callable<String> {
    ExecutorService executorService;
    OriginalCallable callable;

    public DecorateCallable(ExecutorService executorService, OriginalCallable callable) {
        this.executorService = executorService;
        this.callable = callable;
    }

    @Override
    public String call() throws Exception {
        Future<String> future = executorService.submit(callable);
        try {
            return future.get(2000, TimeUnit.SECONDS);
        } catch (TimeoutException | InterruptedException e) {

        }
        return null;
    }
}

如果你决定使用它,你需要加倍池大小:

Executors.newFixedThreadPool(threads * 2);

并在将它们放入最终结果集之前添加一些像if(future.get() != null)这样的条件。

答案 1 :(得分:0)

如果您使用Futures.getChecked,则会吞下超时异常,并且将来会返回null。查看以下代码,其中一个任务抛出TimeoutException,相应的future将返回null。

<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="https://unpkg.com/sweetalert/dist/sweetalert.min.js"></script>
<script src="https://www.google.com/recaptcha/api.js"></script>

<button id="btn1">Submit</button>