2011-01-12 85 views
2

考慮我安排了一個Runnable,以定期執行ScheduledExecutorService,並且出現了像OutOfMemory這樣的一些系統錯誤。它會被無聲地吞下。ScheduledExecutorService可丟失

scheduler.scheduleWithFixedDelay(new Runnable() { 
        @Override 
        public void run() { 
         throw new OutOfMemoryError(); // Swallowed 
        } 
       }, 0, delay, TimeUnit.SECONDS); 

這是正常的嗎?

爲什麼它不傳播到容器?

處理此類錯誤的正確方法是什麼?

謝謝!

回答

2

Error的任何子類型一樣,OutOfMemoryError無法恢復,它們對您的程序通常是致命的。如果你試着去捕捉它,這並不重要,你的程序正在失敗。

但是,如果你的意思是一個Exception而非Error,那麼你有兩個選擇:

  1. 趕上從你的任務的run()方法中的異常。
  2. 致電get()上的Future()scheduleWithFixedDelay()返回。這會將異常傳播回提交線程,但會阻塞,直到發生這種情況。
1

該方法將返回一個ScheduledFuture實例,其get方法(帶或不帶超時)將引發ExecutionException與OutOfMemoryError作爲原因。

+0

所以你建議在調度可重複任務後總是調用future.get()?但是這會導致創建睡眠線程。可以嗎? – 2011-01-12 22:54:37

0

guavaListenableFuture類可能在此處有用。

有了這個,您可以創建一個異常處理程序任務,記錄該錯誤,然後嘗試重新啓動失敗的任務。

你仍然需要睡眠的線程來監視例外,但你只需要在整個過程中的一個全局異常處理線程(而不是爲每個計劃任務。)

0

我個人給你的對象宋樣的機制來報告異常情況,而不是期望一個框架來處理它們。考慮一個異常監聽器或類似的。

對於一個oom,你可以做的事情很少。

這些執行者在那裏執行你的東西,不處理你的代碼可能存在的所有可能的問題!

0

您可以使用從jcabi-logVerboseRunnable類,它捕獲所有異常並記錄他們:

import com.jcabi.log.VerboseRunnable; 
Runnable runnable = new VerboseRunnable(
    Runnable() { 
    public void run() { 
     // do business logic, may Exception occurs 
    } 
    }, 
    true // it means that all exceptions will be swallowed and logged 
); 

現在,當有人來電runnable.run()沒有異常拋出。相反,他們被吞下並記錄(至SLF4J)。