Java Timer vs ExecutorService?
Asked Answered
L

6

310

I have code where I schedule a task using java.util.Timer. I was looking around and saw ExecutorService can do the same. So this question here, have you used Timer and ExecutorService to schedule tasks, what is the benefit of one using over another?

Also wanted to check if anyone had used the Timer class and ran into any issues which the ExecutorService solved for them.

Lifton answered 3/1, 2009 at 21:54 Comment(1)
And if you need something even more featurefull, check out quartz. It gives you a great deal more job control, including cron like scheduling, cluster-aware scheduling, individualized control over jobs (concepts such as one run at a time, dependencies, etc). --TimGarlen
S
358

According to Java Concurrency in Practice:

  • 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.

If you can use ScheduledThreadExecutor instead of Timer, do so.

One more thing... while ScheduledThreadExecutor isn't available in Java 1.4 library, there is a Backport of JSR 166 (java.util.concurrent) to Java 1.2, 1.3, 1.4, which has the ScheduledThreadExecutor class.

Stun answered 3/1, 2009 at 22:22 Comment(1)
Another advantage: if you like lambda expression, Timer cannot use them. ScheduledExecutorService can accept lambda expression because the args it takes is "Runnable" and not "TimerTask".Jacobinism
L
68

If it's available to you, then it's difficult to think of a reason not to use the Java 5 executor framework. Calling:

ScheduledExecutorService ex = Executors.newSingleThreadScheduledExecutor();

will give you a ScheduledExecutorService with similar functionality to Timer (i.e. it will be single-threaded) but whose access may be slightly more scalable (under the hood, it uses concurrent structures rather than complete synchronization as with the Timer class). Using a ScheduledExecutorService also gives you advantages such as:

  • You can customize it if need be (see the newScheduledThreadPoolExecutor() or the ScheduledThreadPoolExecutor class)
  • The 'one off' executions can return results

About the only reasons for sticking to Timer I can think of are:

  • It is available pre Java 5
  • A similar class is provided in J2ME, which could make porting your application easier (but it wouldn't be terribly difficult to add a common layer of abstraction in this case)
Liva answered 4/1, 2009 at 1:19 Comment(2)
Another reason for using TimerTask may be the availability of scheduledExecutionTime() method which doesn't seem to have any equivalent in ScheduledExecutorService.Antiquarian
Another note: I am writing this comment in 2k17, there is no more J2ME. it is already dead.Ileana
P
30

ExecutorService is newer and more general. A timer is just a thread that periodically runs stuff you have scheduled for it.

An ExecutorService may be a thread pool, or even spread out across other systems in a cluster and do things like one-off batch execution, etc...

Just look at what each offers to decide.

Phosphorescent answered 3/1, 2009 at 22:6 Comment(0)
G
10

From Oracle documentation page on ScheduledThreadPoolExecutor

A ThreadPoolExecutor that can additionally schedule commands to run after a given delay, or to execute periodically. This class is preferable to Timer when multiple worker threads are needed, or when the additional flexibility or capabilities of ThreadPoolExecutor (which this class extends) are required.

ExecutorService/ThreadPoolExecutor or ScheduledThreadPoolExecutor is obvious choice when you have multiple worker threads.

Pros of ExecutorService over Timer

  1. Timer can't take advantage of available CPU cores unlike ExecutorService especially with multiple tasks using flavours of ExecutorService like ForkJoinPool
  2. ExecutorService provides collaborative API if you need coordination between multiple tasks. Assume that you have to submit N number of worker tasks and wait for completion of all of them. You can easily achieve it with invokeAll API. If you want to achieve the same with multiple Timer tasks, it would be not simple.
  3. ThreadPoolExecutor provides better API for management of Thread life cycle.

    Thread pools address two different problems: they usually provide improved performance when executing large numbers of asynchronous tasks, due to reduced per-task invocation overhead, and they provide a means of bounding and managing the resources, including threads, consumed when executing a collection of tasks. Each ThreadPoolExecutor also maintains some basic statistics, such as the number of completed tasks

    Few advantages:

    a. You can create/manage/control life cycle of Threads & optimize thread creation cost overheads

    b. You can control processing of tasks ( Work Stealing, ForkJoinPool, invokeAll) etc.

    c. You can monitor the progress and health of threads

    d. Provides better exception handling mechanism

Greatcoat answered 29/10, 2016 at 9:33 Comment(0)
O
6

My reason for sometimes preferring Timer over Executors.newSingleThreadScheduledExecutor() is that I get much cleaner code when I need the timer to execute on daemon threads.

compare

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); 

with

private final Timer timer = new Timer(true);

I do this when I don't need the robustness of an executorservice.

Orpiment answered 12/4, 2015 at 20:52 Comment(0)
D
2

I did had an issue with Timer and I replaced it with ScheduledExecutorService to fix it.

The issue was the Timer depends on System time and everytime I change it, it affects the functioning of the application. So I replaced the Timer with ScheduledExecutorService and now it is working fine.

Denounce answered 10/3, 2021 at 4:6 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.