【问题标题】:Java Timer vs ExecutorService?Java Timer vs ExecutorService?
【发布时间】:2010-09-29 10:11:01
【问题描述】:

我有使用java.util.Timer 安排任务的代码。我环顾四周,看到ExecutorService 也可以这样做。所以这里的这个问题,你有没有用TimerExecutorService来安排任务,用一个比另一个有什么好处?

还想检查是否有人使用过Timer 类并遇到ExecutorService 为他们解决的任何问题。

【问题讨论】:

  • 如果您需要更多功能,请查看quartz。它为您提供了更多的作业控制,包括类似 cron 的调度、集群感知调度、对作业的个性化控制(例如一次运行、依赖关系等概念)。 --蒂姆

标签: java timer scheduled-tasks scheduling executorservice


【解决方案1】:

根据Java Concurrency in Practice

  • Timer 可以对系统时钟的变化敏感,ScheduledThreadPoolExecutor 则不然。
  • Timer 只有一个执行线程,所以长时间运行的任务会延迟其他任务。 ScheduledThreadPoolExecutor 可以配置任意数量的线程。此外,如果需要,您可以完全控制创建的线程(通过提供 ThreadFactory)。
  • TimerTask 中抛出的运行时异常杀死了那个线程,从而使Timer 死亡:-( ... 即计划任务将不再运行。ScheduledThreadExecutor 不仅捕获运行时异常,而且还允许您处理它们如果需要(通过覆盖 ThreadPoolExecutor 中的 afterExecute 方法)。抛出异常的任务将被取消,但其他任务将继续运行。

如果您可以使用ScheduledThreadExecutor 代替Timer,请这样做。

还有一件事……虽然 ScheduledThreadExecutor 在 Java 1.4 库中不可用,但有一个 Backport of JSR 166 (java.util.concurrent) to Java 1.2, 1.3, 1.4,它具有 ScheduledThreadExecutor 类。

【讨论】:

    【解决方案2】:

    如果您可以使用它,那么很难想出一个使用Java 5 执行器框架的原因。调用:

    ScheduledExecutorService ex = Executors.newSingleThreadScheduledExecutor();
    

    会给你一个ScheduledExecutorService,其功能与Timer 相似(即它将是单线程的),但其访问可能更具可扩展性(在后台,它使用并发结构而不是完全同步) Timer 类)。使用ScheduledExecutorService 还可以为您带来以下优势:

    • 如果需要,您可以对其进行自定义(参见 newScheduledThreadPoolExecutor()ScheduledThreadPoolExecutor 类)
    • “一次性”执行可以返回结果

    我能想到的坚持Timer的唯一理由是:

    • 它在 Java 5 之前可用
    • J2ME 中提供了一个类似的类,它可以使您的应用程序更容易移植(但在这种情况下添加一个公共抽象层并不是很困难)

    【讨论】:

    • 使用TimerTask 的另一个原因可能是scheduledExecutionTime() 方法的可用性,它似乎在ScheduledExecutorService 中没有任何等效项。
    • 另外说明:我在2k17写这个评论,没有J2ME了。它已经死了。
    • Java Timer 类很糟糕。
    【解决方案3】:

    ExecutorService 更新且更通用。计时器只是一个定期运行您为其安排的内容的线程。

    一个 ExecutorService 可能是一个线程池,甚至可以分布在集群中的其他系统上,并执行一次性批量执行等操作......

    看看每个提供什么来决定。

    【讨论】:

      【解决方案4】:

      这里有一些关于计时器使用的更多好的做法:

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

      一般来说,我会将 Timer 用于快速而肮脏的东西,而 Executor 用于更强大的使用。

      【讨论】:

        【解决方案5】:

        来自ScheduledThreadPoolExecutor上的 Oracle 文档页面

        一个ThreadPoolExecutor,可以额外安排命令在给定延迟后运行,或定期执行。当需要多个工作线程或需要 ThreadPoolExecutor(此类扩展)的额外灵活性或功能时,此类优于 Timer

        ExecutorService/ThreadPoolExecutorScheduledThreadPoolExecutor 在您有多个工作线程时是显而易见的选择。

        ExecutorService 优于 Timer

        1. ExecutorService 不同,Timer 无法利用可用的 CPU 内核,尤其是在使用ExecutorService 风格的多个任务时,例如ForkJoinPool
        2. 如果您需要在多个任务之间进行协调,ExecutorService 提供了协作 API。假设您必须提交 N 个工作任务并等待所有任务完成。您可以使用invokeAll API 轻松实现它。如果您想通过多个Timer 任务实现相同的目标,那就不简单了。
        3. ThreadPoolExecutor 为管理线程生命周期提供了更好的 API。

          线程池解决了两个不同的问题:由于减少了每个任务的调用开销,它们通常在执行大量异步任务时提供改进的性能,并且它们提供了一种限制和管理资源(包括线程)在执行时消耗的方法一组任务。每个 ThreadPoolExecutor 还维护一些基本的统计信息,比如完成任务的数量

          几个优点:

          一个。您可以创建/管理/控制线程的生命周期并优化线程创建成本开销

          b.您可以控制任务的处理(Work Stealing、ForkJoinPool、invokeAll)等。

          c。您可以监控线程的进度和健康状况

          d。提供更好的异常处理机制

        【讨论】:

          【解决方案6】:

          我有时更喜欢 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 的健壮性时,我会这样做。

          【讨论】:

            【解决方案7】:

            我确实遇到了 Timer 问题,我将其替换为 ScheduledExecutorService 来修复它。

            问题是 Timer 取决于系统时间,每次我更改它时,都会影响应用程序的功能。所以我用 ScheduledExecutorService 替换了 Timer,现在它工作正常了。

            【讨论】:

              猜你喜欢
              • 2019-02-17
              • 1970-01-01
              • 1970-01-01
              • 2012-10-30
              • 2015-01-12
              • 2018-08-04
              • 2016-05-07
              • 2016-07-23
              • 2020-07-16
              相关资源
              最近更新 更多