我有使用java.util.Timer调度任务的代码。我环顾四周,发现ExecutorService也能做到这一点。这里的问题是,你是否使用Timer和ExecutorService来调度任务,使用它们有什么好处?

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


当前回答

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

其他回答

ExecutorService更新且更通用。计时器只是一个线程,它周期性地运行你为它安排的事情。

ExecutorService可以是一个线程池,甚至可以分布在集群中的其他系统中,执行诸如一次性批处理执行之类的事情……

只要看看每家公司提供的服务就能决定。

根据Java并发实践:

Timer can be sensitive to changes in the system clock, ScheduledThreadPoolExecutor isn't. Timer has only one execution thread, so long-running task can delay other tasks. ScheduledThreadPoolExecutor can be configured with any number of threads. Furthermore, you have full control over created threads, if you want (by providing ThreadFactory). Runtime exceptions thrown in TimerTask kill that one thread, thus making Timer dead :-( ... i.e. scheduled tasks will not run anymore. ScheduledThreadExecutor not only catches runtime exceptions, but it lets you handle them if you want (by overriding afterExecute method from ThreadPoolExecutor). Task which threw exception will be canceled, but other tasks will continue to run.

如果你可以使用ScheduledThreadExecutor而不是Timer,那么就这样做。

还有一件事……虽然ScheduledThreadExecutor在Java 1.4库中不可用,但JSR 166 (Java .util.concurrent)有一个到Java 1.2、1.3、1.4的Backport,其中有ScheduledThreadExecutor类。

我确实有定时器的问题,我用ScheduledExecutorService替换了它来修复它。

问题是定时器取决于系统时间,每次我改变它,它会影响应用程序的功能。所以我用ScheduledExecutorService替换了Timer,现在它工作得很好。

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

如果您可以使用Java 5执行程序框架,那么就很难想出不使用它的理由。调用:

ScheduledExecutorService ex = Executors.newSingleThreadScheduledExecutor();

将为您提供一个ScheduledExecutorService,具有与Timer类似的功能(即它将是单线程的),但其访问可能更具伸缩性(在底层,它使用并发结构,而不是像Timer类那样完全同步)。使用ScheduledExecutorService还可以为您提供以下优势:

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

我能想到的坚持使用Timer的唯一原因是:

它在Java 5之前可用 J2ME中提供了一个类似的类,它可以使移植应用程序更容易(但在本例中添加一个公共抽象层并不难)