CosmoCode
  • Great software.

  • Bright people.

  • Happy customers!

CosmoCode GmbH
  • Home
  • Skills
  • About Us
  • References
  • Blog
  • Open Source
←
All blogposts
→

Uncaught exceptions in scheduled tasks

Uncaught exceptions in scheduled tasks

Let this post be a little field report about exception handling in the Java Executor Framework. The famous UncaughtExceptionHandler One of the most useful things for exception handling in multithreaded systems (since Java 5) is the Thread.UncaughtExceptionHandler which can be used to handle unchecked exceptions being thrown from inside the run()-method of a Runnable. Using it in addition with the new Executor framework works like a charm.

Willi S., 12/17/2009 1:44 a.m.

 

3771278549_ed18319f3f_o.jpg

Let this post be a little field report about exception handling in the Java Executor Framework.

The famous UncaughtExceptionHandler

One of the most useful things for exception handling in multithreaded systems (since Java 5) is the Thread.UncaughtExceptionHandler which can be used to handle unchecked exceptions being thrown from inside the run()-method of a Runnable. Using it in addition with the new Executor framework works like a charm.

Here we create an ExecutorService which should use our custom ThreadFactory implementation to (surprise, surprise) create new Threads.

final ThreadFactory factory = new ThreadFactory() {
 
    @Override
    public Thread newThread(Runnable target) {
        final Thread thread = new Thread(target);
        log.debug("Creating new worker thread");
        thread.setUncaughtExceptionHandler(new UncaughtExceptionHandler() {
 
            @Override
            public void uncaughtException(Thread t, Throwable e) {
                log.error("Uncaught Exception", e);
            }
 
        });
        return thread;
    }
 
};
final ExecutorService executor = Executors.newCachedThreadPool(factory);

If the service executes a task which fails due to an unchecked exception, our exception handler will log the failure. (I am avoiding the word “handle” here, because logging an exception should not be considered handling it, but that's another story.)

Scheduled task execution

It's getting interesting if you want to use a ScheduledExecutorService.

final ScheduledExecutorService scheduler = Executors.newSingleThreadScheduledExecutor(factory);
scheduler.scheduleAtFixedRate(task, delay, period, unit);

Let's assume factory is the same ThreadFactory as defined above. My first assumption was that my exception logging technique would work the same. Long story short, it didn't. Of course your factory will be used by the executor, but the uncaught exeception handler just never gets called, which makes all exceptions just disappear without notice - a debugging nightmare.

Have you seen my exception?

There is a totally different, and in my opinion not intuitive, way to receive exceptions when scheduling tasks for future executions.

final ScheduledFuture<?> future = scheduler.scheduleAtFixedRate(task, delay, period, unit);

The scheduleAtFixedRate method (like all schedule and submit-methods) returns a Future which represents a pending completion. You can use this object e.g. to fetch the state of the execution. In case of a scheduled task, you will receive a ScheduledFuture which adds another element to the nature of a Future. It does not only represent a pending completion, it also represents a pending execution. This does make totally sense in case there is a task which is scheduled to run exactly once. But in case of a periodic execution, the meaning of a pending completion is absurd, because the only thing we can assure is that it will never finish. It's like waiting for cron to stop running jobs. That's his job, we don't expect him to stop ever.

This code block shows how to actually receive the exception.

scheduler.execute(new Runnable() {
 
    @Override
    public void run() {
        try {
            future.get();
            // dead code here?
        } catch (InterruptedException e) {
            log.error("Scheduled execution was interrupted", e);
        } catch (CancellationException e) {
            log.warn("Watcher thread has been cancelled", e);
        } catch (ExecutionException e) {
           log.error("Uncaught exception in scheduled execution", e.getCause());
        }
    }
 
});

We call future.get(), which blocks until the execution completes (haha!). It will throw an ExecutionException in case an unchecked exception is thrown. That's what we were looking for, hooray!

The comment after the get() call indicates where you can place code you never want to get executed. In case of a periodically scheduled execution, the future will never return normally. (You shouldn't read too much into the last part.) If the corresponding scheduled task gets removed from the schedule you will get the CancellationException. So again, the only way the jvm leaves the try-block is by throwing exceptions.

To make the above example work, it's necessary to make the scheduler a threadpool, instead of a single thread. Otherwise the watcher thread will block at the get() call and therefore prevent the scheduler from executing any other task.

final ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(2);

Where is ScheduledExecutorService.awaitTermination()?

I would have expected a method called awaitTermination (or something similar), which blocks until someone made the executor stop executing my task. The javadoc of get() states:

Waits if necessary for the computation to complete, and then retrieves its result.

Everything after Waits is basically a lie when dealing with periodically scheduled tasks and should, in my opinion, be overriden and re-documented in ScheduledFuture to point out the difference.

Read more

  • jsr223/javax.script experiences and problems
  • Launch TheLabelFinder.com
  • Publizieren in Rhino
  • CosmoCode sucht studentische Mitarbeiter (JAVA Entwickler)
  • autounboxing NullPointerException
  • Intelligente Android REST Autocompletion
  • Maven - Java Project Management
  • rhino again
  • Schwedenurlaub mit CosmoCode
  • Java, a developer's island without trees

Need to catch the exception?

This Blog Post is brought to you by CosmoCode,a Web Agency located in Berlin / Germany.

CosmoCode has a long time experience in building individual software solutions, as well as Typo3 CMS und Wikisolutions based on DokuWiki.

And of course we are specialists in diverse programming languages, databases, cutting edge Frontend technologies and mobile Development.

Need a professional web development agency?

Dont hesitate to get in contact with us.

  • Use the contact form below,
  • send us an email to info@cosmocode.de
  • or give us a call (+49 30 814 50 40 80)

See you soon!

  • Need a professional web development agency?

Contact

Thank you for your interest!
Get in contact:

CosmoCode GmbH

Prenzlauer Allee 36G
10405 Berlin

Phone: +49 30 814 50 40 70

Fax: +49 30 2809 7093


mail: info@cosmocode.de

CosmoCode GmbH  
   

© CosmoCode 2021 | Imprint | Data Privacy | Cookies verwalten

Close
Deutsch English
  • Jobs