首页 文章

Java Timer vs ExecutorService?

提问于
浏览
237

我有代码,我使用 java.util.timer 安排任务 . 我环顾四周,看到 ExecutorService 可以做同样的事情 . 所以这个问题,你有没有使用Timer和 ExecutorService 来安排任务,一个人使用另一个人的好处是什么?

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

6 回答

  • 276

    根据Java Concurrency in Practice

    • Timer 可能对系统时钟的变化很敏感, ScheduledThreadPoolExecutor 不是 .

    • Timer 只有一个执行线程,因此长时间运行的任务可以延迟其他任务 . ScheduledThreadPoolExecutor 可以配置任意数量的线程 . 此外,如果需要,您可以完全控制已创建的线程(通过提供 ThreadFactory ) .

    • TimerTask 中抛出的运行时异常会杀死一个线程,从而使 Timer 死了:-( ...即计划任务将不再运行. ScheduledThreadExecutor 不仅捕获运行时异常,而且可以让你根据需要处理它们(通过覆盖 afterExecute 方法)来自 ThreadPoolExecutor ) . 抛出异常的任务将被取消,但其他任务将继续运行 .

    如果您可以使用 ScheduledThreadExecutor 而不是 Timer ,请执行此操作 .

    还有一件事......虽然在Java 1.4库中没有 ScheduledThreadExecutor ,但是有一个Backport of JSR 166 (java.util.concurrent) to Java 1.2, 1.3, 1.4,它有 ScheduledThreadExecutor 类 .

  • 5

    如果's available to you, then it'很难想到不使用Java 5 Actuator 框架的原因 . 呼叫:

    ScheduledExecutorService ex = Executors.newSingleThreadScheduledExecutor();
    

    会给你 ScheduledExecutorService 具有与 Timer 类似的功能(即它将是单线程的),但其访问可能稍微更具可扩展性(在引擎盖下,它使用并发结构而不是像 Timer 类那样完全同步) . 使用 ScheduledExecutorService 还可以为您提供以下优势:

    • 如果需要,您可以自定义它(参见 newScheduledThreadPoolExecutor()ScheduledThreadPoolExecutor 类)

    • 'one off'执行可以返回结果

    关于坚持 Timer 的唯一原因我能想到的是:

    • 它在Java 5之前可用

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

  • 22

    ExecutorService更新,更通用 . 计时器只是一个定期运行您为其安排的东西的线程 .

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

    只需看看每个提供的决定 .

  • 3

    这里有一些关于Timer使用的更好的做法:

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

    一般来说,我会使用Timer来快速和脏的东西和Executor使用更强大 .

  • 59

    我有时更喜欢Timer over 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);
    

    当我不需要 Actuator 服务的健壮性时,我这样做 .

  • 14

    来自ScheduledThreadPoolExecutor上的Oracle文档页面

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

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

    ExecutorService 的优点 Timer

    • Timer 无法利用可用的CPU核心,而不像 ExecutorService ,尤其是使用 ExecutorService 的_1192242_类似的多个任务
      如果您需要在多个任务之间进行协调,

    • ExecutorService 会提供协作API . 假设您必须提交N个工作任务并等待所有这些任务完成 . 您可以使用invokeAll API轻松实现它 . 如果你想用多个 Timer 任务实现相同的目标,那就不简单了 .

    • ThreadPoolExecutor为管理线程生命周期提供了更好的API .

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

    几个优点:

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

    湾您可以控制任务的处理(工作窃取,ForkJoinPool,invokeAll)等 .

    C . 您可以监视线程的进度和运行状况

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

相关问题