[英]Partial retrieval of data from a batch of tasks
我正在使用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!
}
這里的問題是-如果其中一項任務花費的時間超過2000ms,則將拋出TimeoutException
,盡管某些任務可能已在此時完成,但響應中我什么也得不到。
因此,我想檢索已完成的任務的響應(無論是部分響應還是完成響應),直到超時(2000毫秒)。 例如:
(相對於批處理調用的START_TIME的時間)
任務1:1000ms
任務2: 3000ms
任務3:1800ms
輸出:
超時異常
所需輸出:
好極了! <-對應於任務1
好極了! <-對應於任務3
我想到的一種解決方案是單獨獲取期貨並將其超時設置為MAX(0, TIME_OUT - TIME_NOW - START_TIME)
。 這可能有效,但對我來說似乎不是一個干凈的解決方案。
您可以使用裝飾可調用對象來處理超時。
假設這是原始可調用對象:
class OriginalCallable implements Callable<String> {
@Override
public String call() throws Exception {
return "";
}
}
您可以使用此原始Callable和執行程序構造一個裝飾Callable:
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)
類的條件。
如果使用Futures.getChecked,則會吞下超時異常,並且future將返回null。 簽出以下代碼,其中一項任務拋出TimeoutException,而相應的future返回null。
import java.io.IOException;
import com.google.common.util.concurrent.*;
import java.time.*;
import java.util.*;
import java.util.concurrent.*;
import java.util.stream.*;
public class App
{
public static void main( String[] args ) throws InterruptedException, ExecutionException
{
ListeningExecutorService listeningExecutorService = MoreExecutors.listeningDecorator(Executors.newFixedThreadPool(5));
ListenableFuture<String> future1 =
listeningExecutorService.submit(() -> {
throw new TimeoutException("Timeout exception");
});
ListenableFuture<String> future2 =
listeningExecutorService.submit(() -> "Hello World");
ListenableFuture<List<String>> combined = Futures.successfulAsList(future1, future2);
try {
String greeting = Futures.getChecked(combined, IOException.class, 2000l, TimeUnit.MILLISECONDS).stream().collect(Collectors.joining(" "));
System.out.println(greeting);
} catch (IOException e) {
System.out.println("Exception: " + e.getMessage());
} finally {
listeningExecutorService.shutdown();
}
}
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.