簡體   English   中英

Java 定時器 vs ExecutorService?

[英]Java Timer vs ExecutorService?

我有使用java.util.Timer安排任務的代碼。 我環顧四周,看到ExecutorService可以做同樣的事情。 所以這個問題,你有沒有使用TimerExecutorService來安排任務,一個使用另一個的好處是什么?

還想檢查是否有人使用了Timer類並遇到了ExecutorService為他們解決的任何問題。

根據實踐中的Java並發

  • Timer可能對系統時鍾的變化敏感,而ScheduledThreadPoolExecutor則不然。
  • Timer只有一個執行線程,因此長時間運行的任務可以延遲其他任務。 ScheduledThreadPoolExecutor可以配置任意數量的線程。 此外,如果需要,您可以完全控制創建的線程(通過提供ThreadFactory )。
  • 運行時異常拋出TimerTask殺一個線程,從而使Timer死:-( ...即計划的任務將不再運行。 ScheduledThreadExecutor不僅捕獲運行時異常,但它可以讓你處理它們,如果你想(通過重載afterExecute從方法ThreadPoolExecutor ). 拋出異常的任務將被取消,但其他任務將繼續運行。

如果您可以使用ScheduledThreadExecutor而不是Timer ,請這樣做。

還有一件事......雖然ScheduledThreadExecutor在 Java 1.4 庫中不可用,但有一個JSR 166 ( java.util.concurrent ) 到 Java 1.2, 1.3, 1.4 的 Backport ,它具有ScheduledThreadExecutor類。

如果您可以使用它,那么很難找到使用 Java 5 執行器框架的理由。 調用:

ScheduledExecutorService ex = Executors.newSingleThreadScheduledExecutor();

將為您提供一個與Timer功能相似的ScheduledExecutorService (即它將是單線程的),但其訪問的可擴展性可能稍微提高一些(在幕后,它使用並發結構而不是像Timer類那樣完全同步)。 使用ScheduledExecutorService還可以為您帶來以下優勢:

  • 如果需要,您可以自定義它(請參閱newScheduledThreadPoolExecutor()ScheduledThreadPoolExecutor類)
  • “一次性”執行可以返回結果

關於堅持使用Timer我能想到的唯一原因是:

  • 它在 Java 5 之前可用
  • J2ME 中提供了一個類似的類,它可以使您的應用程序更容易移植(但在這種情況下添加一個公共抽象層並不是非常困難)

ExecutorService 更新且更通用。 計時器只是一個線程,它定期運行您為其安排的內容。

ExecutorService 可能是一個線程池,甚至分布在集群中的其他系統中,並執行一次性批處理等操作...

只要看看每個人提供什么來決定。

以下是有關 Timer 使用的更多好做法:

http://tech.puredanger.com/2008/09/22/timer-rules/

一般來說,我會使用 Timer 來處理快速和骯臟的東西,而使用 Executor 來實現更強大的使用。

來自ScheduledThreadPoolExecutor上的 Oracle 文檔頁面

一個ThreadPoolExecutor可以額外安排命令在給定延遲后運行,或定期執行。 當需要多個工作線程時,或者需要 ThreadPoolExecutor(此類擴展)的額外靈活性或功能時,此類比Timer更可取。

當您有多個工作線程時, ExecutorService/ThreadPoolExecutorScheduledThreadPoolExecutor是顯而易見的選擇。

ExecutorService優於Timer

  1. ExecutorService不同, Timer無法利用可用的 CPU 內核,尤其是在使用ForkJoinPoolExecutorService風格的多個任務時
  2. 如果您需要在多個任務之間進行協調, ExecutorService提供了協作 API。 假設您必須提交 N 個工作任務並等待所有任務完成。 您可以使用invokeAll API 輕松實現它。 如果你想用多個Timer任務來達到同樣的效果,那可就不是那么簡單了。
  3. ThreadPoolExecutor為管理線程生命周期提供了更好的 API。

    線程池解決兩個不同的問題:由於減少了每個任務的調用開銷,它們通常在執行大量異步任務時提供改進的性能,並且它們提供了一種限制和管理資源的方法,包括在執行集合時消耗的線程任務。 每個 ThreadPoolExecutor 還維護一些基本的統計信息,比如完成的任務數

    幾個優點:

    a. 您可以創建/管理/控制線程的生命周期並優化線程創建成本開銷

    您可以控制任務的處理(工作竊取、ForkJoinPool、invokeAll)等。

    C. 您可以監控線程的進度和健康狀況

    d. 提供更好的異常處理機制

我有時更喜歡 Timer 而不是 Executors.newSingleThreadScheduledExecutor() 的原因是,當我需要計時器在守護線程上執行時,我得到了更清晰的代碼。

比較

private final ThreadFactory threadFactory = new ThreadFactory() {
    public Thread newThread(Runnable r) {
        Thread t = new Thread(r);
        t.setDaemon(true);
        return t;
    }
};
private final ScheduledExecutorService timer = Executors.newSingleThreadScheduledExecutor(threadFactory); 

private final Timer timer = new Timer(true);

當我不需要 executorservice 的健壯性時,我會這樣做。

我確實遇到了 Timer 問題,我用 ScheduledExecutorService替換了它來修復它。

問題是計時器取決於系統時間,每次我更改它時,它都會影響應用程序的功能。 所以我用ScheduledExecutorService替換了Timer ,現在它工作正常。

暫無
暫無

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

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