[英]Exception handling with multiple futures from ScheduledExecutorService
我正在使用ScheduledExecutorService,向其中添加了提交Runnable和計划Runnable(使用scheduleWithFixedDelay)。 目的是要有非常長的運行進程,因此我的所有可運行變量都沒有定義的生存期。 我基本上希望主線程僅對異常和中斷做出反應。 計划的任務很關鍵,例如生成熱信號,因此,如果有任何線程拋出運行時異常,我想記錄該異常,中止所有其他線程並關閉程序。
我應該如何處理例外情況? ScheduledExecutorService會吞下所有異常,除非我運行Future.get()。
像下面這樣循環遍歷期貨是行不通的。 如果期貨列表中的第一項未返回任何錯誤,則該錯誤將阻止該線程偵聽可能返回錯誤的其他線程。
for (Future<?> future : futures) {
future.get();
}
一種選擇是遍歷期貨,詢問是否完成,如下所示,但我不太喜歡這種解決方案。 我需要添加線程睡眠,因此對異常的響應被延遲。
boolean allActive = true;
while (allActive) {
for (Future<?> future : futures) {
if (!future.isDone()) {
allActive = false;
break;
}
}
Thread.sleep(50);
}
我還有什么其他選擇? 還是我處理問題的方式不對? 我不應該完全使用ScheduledExecutorService自己在自己的線程中實現計划嗎?
示例代碼,請嘗試將順序更改為將來的列表! 我想要您在handle2之前添加handle的行為,但是列表的順序無關緊要:
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
public class Test {
private static int i = 0;
public static void main(String[] args) throws Exception {
ScheduledExecutorService scheduler = Executors.newSingleThreadScheduledExecutor();
Future<?> handle = scheduler.scheduleWithFixedDelay(new Runnable() {
public void run() {
System.out.println("No exception!");
if (i > 2) {
System.out.println("Exception!");
throw new RuntimeException("foo");
}
i++;
}
}, 0, 500, TimeUnit.MILLISECONDS);
Future<?> handle2 = scheduler.scheduleWithFixedDelay(new Runnable() {
public void run() {
System.out.println("Running!");
}
}, 0, 500, TimeUnit.MILLISECONDS);
List<Future<?>> futures = new ArrayList<>();
futures.add(handle2);
futures.add(handle);
try {
for (Future<?> future : futures) {
future.get();
}
} catch (Exception e) {
scheduler.shutdownNow();
System.out.println(scheduler.awaitTermination(1, TimeUnit.SECONDS));
System.out.println("Shuwdown complete");
e.printStackTrace();
}
}
}
您可以使用Listener或Observer-Like模式來做到這一點:
interface IFutureListener{
void onException( Throwable t );
}
final IFutureListener errHandler = new IFutureListener(){
@override public void onException( Throwable t ){
// shutdown Service here
}
};
// ...
Future<?> handle = scheduler.scheduleWithFixedDelay(new Runnable() {
final IFutureListener callback = errHandler;
public void run() {
try{
System.out.println("No exception!");
if (i > 2) {
System.out.println("Exception!");
throw new RuntimeException("foo");
}
i++;
}
catch( Exception ex ){
callback.onException(ex);
}
}
}, 0, 500, TimeUnit.MILLISECONDS);
您可能仍需要對此進行一些調整,但這是要點。
@ dimo414在評論中寫的番石榴的ListenableFuture將為您提供類似的功能。 但是,如果您不希望/不允許使用第三方,則可以使用這種方法自己實現。
感謝@efekctive:我也建議記錄異常。 除非您確切知道自己在做什么,否則幾乎絕不應該默默地吞下它們。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.