Steve Chambers Steve Chambers - 10 months ago 52
Java Question

How to handle errors in a repeated task using ScheduledExecutorService?

I have a

, which invokes a Runnable periodically via
(could have used

Am now considering what to do if an error occurs. If it's something that can't easily be recovered from(*) I'd like the option of stopping all further invocations but not sure of the best way of doing this.

Apparently checked exceptions can't be thrown from a Runnable so would appreciate any guidance on how to choose from the following:

Throw a custom RuntimeException myself?
Something else?

(*) Would like to know the general case but in case anyone's interested, the checked exception I'm currently looking at is a ParserConfigurationException thrown from DocumentBuilderFactory.newDocumentBuilder(). If this is thrown, it indicates a serious problem so I'd basically like the scheduling to completely stop rather than potentially repeating the error every time.

Answer Source

Based on a few of the helpful comments above here's the gist of my current code - a few q's remain within so would welcome any further comments:

public class ScheduledTask implements Runnable {
    // Configurable values
    private static final int CORE_THREAD_POOL_SIZE = 1;
    private static final int INITIAL_DELAY_MS = 0;
    private static final int INTERVAL_MS = 1000;

    private final ScheduledExecutorService scheduledExecutorService = 

    private ScheduledFuture<?> scheduledFuture;

    public void run() {
        try {
            try {
                // Do stuff
            } catch RecoverableCheckedException rce { // E.g. SAXException
                // Log and handle appropriately
        } catch UnrecoverableCheckedException uce { // E.g. ParserConfigurationException
            // Not 100% happy with this. It means the caller would need to call
            // getCause() to get the real Exception in this case. But other 
            // RuntimeExceptions wouldn't be wrapped. Could consider catching
            // and wrapping all RuntimeExceptions but I like that even less!
            throw new RuntimeException(uce);

    public boolean isScheduling() {
        return (this.scheduledFuture != null)
               && (!this.scheduledFuture.isDone());

    // May not be needed but provided in case this class is shared.
    public boolean isShutdown() {
        return scheduledExecutorService.isShutdown();

    public void start() {
        // If the Executor Service has already been shutdown, would expect
        // a RejectedExecutionException to be thrown here(?) Not sure what
        // would happen if this method were called when isScheduling() is
        // true?
        this.scheduledFuture = 

    // To be called once at the very end - e.g. on program termination.
    public void shutdown() {