簡體   English   中英

檢索使用ScheduledExecutorService計划的任務實例

[英]Retrieving a task instance scheduled with ScheduledExecutorService

我有一個ScheduledExecutorService用於在JEE環境中進行任務調度。 其中一些任務在被ScheduledExecutorService.shutdownNow()中斷時使資源處於打開狀態(例如,使用第三方庫(如Lucene)打開文件)。

我知道一個線程可能不會自己停止執行:停止線程的必須使用的方法是檢查中斷標志並停止方法的執行,以及線程是否處於阻塞狀態(例如,wait(),sleep()等)。或者,如果在可中斷的通道中執行某些IO操作,則Thread.interrupt()將引發InterruptedException 在這兩種情況下,必須執行finally塊。 請參閱: http : //download.oracle.com/javase/1,5.0/docs/api/java/lang/Thread.html#interrupt%28%29

顯然,我已經嘗試在Task類中使用一個實施得很好的final塊來釋放資源,但是在某些環境(例如CentOS)中,當線程中斷時,finally塊不會執行。 然后我在官方Java文檔中發現了這個非常酷的注釋:

注意:如果在執行try或catch代碼時JVM退出,則finally塊可能不會執行。 同樣,如果執行try或catch代碼的線程被中斷或殺死,即使整個應用程序繼續運行,finally塊也可能不會執行。

因此,我需要引用所有已調度的任務,以便在Task類中實現一些強制釋放資源的公共方法。 我可以從ScheduledExecutorService檢索對任務類的那些引用嗎? 還是您有一些好主意,可以更好地解決我的問題?

第一個解決方案:把它包起來!

ScheduledExecutorService創建Wrapper類,並添加如下屬性:

private IdentityHashMap<ScheduledFuture<?>, Runnable> taskList;

這樣,我們可以直接訪問任何Runnable對象,也可以通過與其相關的ScheduledFuture訪問它。 對於包裝器的實例化,我可以從Executors.newScheduledThreadPool()方法獲取ScheduledExecutorService並將其傳遞給我的包裝器。

另一個解決方案:擴展它!

擴展ScheduledThreadPoolExecutor ,添加IdentityHashMap屬性,並覆蓋所有計划或取消作業的方法,以從地圖添加/刪除引用。

兩種解決方案都存在問題?

如果包裝器或擴展類的調用者收到SchedulerFuture<?>對象,則可以使用SchedulerFuture<?>.cancel()方法取消作業,從而繞過“膠囊”。 使用包裝程序,您可以避免將SchedulerFuture<?>引用傳遞給調用方,但是使用擴展類則不能(如果在擴展類中創建自己的方法,則將獲得與包裝程序相同的結果,但是在非常令人困惑的方式)。

優雅的解決方案:您自己的調度程序! 感謝Kaj指出...

  1. 擴展ScheduledThreadPoolExecutor以覆蓋decorateTask()方法
  2. 使用ScheduledFuture接口的一種實現來裝飾Runnable
  3. 實現一個自定義的cancel()方法,該方法實際上取消線程,但也操縱Runnable對象以強制釋放資源。

檢查我的博客文章的詳細信息和代碼示例!

您要安排什么時間? 任務是什么樣的? 我發現很難相信未執行finally塊。 我想這是您已計划的任務,但是尚未開始執行的任務正在泄漏資源(因為它們的finally塊將不會執行)

如果CentOS上沒有真正執行這些finally塊,這聽起來像是一個糟糕的VM實現。 在其他任何VM實施中都沒有聽說過。

您可以執行一個選擇,而不是引用所有計划的任務,是對ScheduledThreadPoolExecutor進行子類化,並覆蓋decorateTask方法,以便它們使用您的類來裝飾任務,然后攔截取消調用。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM