可通过 while 循环调用

Callable with while loop

我需要提供使用 ExecutorService、Callable 和 Future 进行一些计算并打印部分结果直到达到定义条件的代码。我首先想到的是使用 while 循环。不幸的是,据我所知 ExecutorService.get() 等到任务完成,所以我不能做类似(伪代码)的事情:

public Object call() throws Exception {
  try {
    while(!condition)           {
      //perform calc
      return partialCalculationResult;
    }
  }
  catch(InterruptedException e){ 
  }
}

谁能指导我正确的方向是什么?

肮脏的选项是在 while 循环中放置一个 System.out.println

更简洁的选项是 publish/subscriber 模式,例如:

interface Subscriber {
    void onPartialResult(double partialResult);
}
class SystemOutSubscriber implements Subscriber{
    @Override
    void onPartialResult(double partialResult) {
        System.out.println(partialResult);
    }
}
class YourCalculatorClass {
    List<Subscriber> subscribers = ...
    public Object call() throws Exception {
       while(!condition) {
          //perform calc
          for(Subscriber s : subscribers) {
              s.onPartialResult(partialCalculationResult);
           }
        }
     }
}

这里是:

while(!condition) {
  //perform calc
  return partialCalculationResult;
}

表示您的逻辑中有一个"hole"。这可能应该是这样的:

while(!condition) {
  // perform computation
  push intermediate results somewhere
}
return finalResult;

换句话说:您在这里谈论 两个 不同的元素。对于那些 "progress" 更新,您将需要某种共享数据结构;例如 Queue

你看,与其他语言不同,没有内置的 "generator" 概念可以让你从循环中 yield 值;例如,就像您在 python or scala 中所做的那样。

您可以使用 Thread.interrupt 停止 while 循环内的线程并将剩余结果添加到列表中

while(!condition){ list.add(addResultHere) Thread.interrupt(); }

下面是一个使用 ExecutorService 的小例子 推送可调用任务。为了示例的方便,我现在将它们放在一个 while 循环中,但它们可以来自任何地方。 callable 本身当然使用了最简单的例子,它接受一个数字。如果数字低于 5,一切都很好,我们 return 一个文本。如果没有,我们 return 什么都没有。当评估未来并且结果为空时,我们关闭 ExecutorService 并结束它。因此,这是一个使用 ExecutorServiceCallableFuture 来做一些事情的示例,至少与我从您的解释中可以看出的内容相似。

public ExecutorServiceTest() {
    ExecutorService service = Executors.newCachedThreadPool();
    int num = 0;
    while (true) {
        Future<Optional<String>> future = service.submit(new MyCallable(num++));

        try {
            Optional<String> result = future.get();
            if (!result.isPresent()) {
                service.shutdown();
                break;
            }
            System.out.println(result.get());
        } catch (InterruptedException | ExecutionException e) {
            e.printStackTrace();
            service.shutdown();
        }
    }
}

private static class MyCallable implements Callable<Optional<String>> {
    private final int num;

    MyCallable(int num) {
        this.num = num;
    }

    @Override
    public Optional<String> call() throws Exception {
        if (num < 5)
            return Optional.of("My number is " + num);
        return Optional.empty();
    }
}

public static void main(String[] args) {

    new ExecutorServiceTest();
}