Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

If a task encounters an exception, its further executions are suppressed. Why?

The docs for scheduleAtFixedRate and scheduleWithFixedDelay say that:

If any execution of the task encounters an exception, subsequent executions are suppressed

Assuming that my tasks were designed to do some network job and the host was not found. Will the tasks not be executed again ? It may happen that the host is back online the next moment.

Assuming what the docs were talking about was an instance of RuntimeException, like array index out of bounds, will tasks will never ever be executed again ? What if I want them to keep executing ?

like image 702
An SO User Avatar asked Nov 20 '25 05:11

An SO User


2 Answers

will tasks will never ever be executed again?

That's what "subsequent executions are suppressed" means, isn't it?

What if I want them to keep executing ?

Don't let RuntimeExceptions and Errors escape from them.

like image 126
user207421 Avatar answered Nov 21 '25 17:11

user207421


Check about uncatched exceptions inside Runnable action, that you execute by Scheduler. By default JVM don't catch them and thread crashed unnoticed.


I suggest to use custom ScheduledThreadPoolExecutor, like this:

static class MyScheduledThreadPoolExecutor extends ScheduledThreadPoolExecutor {
    public MyScheduledThreadPoolExecutor(int corePoolSize,ThreadFactory threadFactory) {
        super(corePoolSize, threadFactory);
    }

    @Override
    public ScheduledFuture<?> schedule(Runnable command, long delay,TimeUnit unit) {
        return super.schedule(new SheduleExceptionCatcher(command), delay, unit);
    }


    @Override
    public ScheduledFuture<?> scheduleAtFixedRate(Runnable command,long initialDelay, long period, TimeUnit unit) {
        return super.scheduleAtFixedRate(new SheduleExceptionCatcher(command), initialDelay, period, unit);
    }

    @Override
    public ScheduledFuture<?> scheduleWithFixedDelay(Runnable command,long initialDelay, long delay, TimeUnit unit) {
        return super.scheduleWithFixedDelay(new SheduleExceptionCatcher(command), initialDelay, delay, unit);
    }


    /** Wrap for Runnable - for error catching */
    private static class SheduleExceptionCatcher implements Runnable {
        private Runnable task;
        public SheduleExceptionCatcher(Runnable task) {
            this.task = task;
        }

        @Override
        public void run() {
            try {
                task.run();
            } catch (Throwable e) {
                System.err.println("" + e); // or some logger probably
            }
        }
    }
}

And make some test:

public static void main(String[] args) {
    new MyScheduledThreadPoolExecutor(2, new PriorityThreadFactory("GeneralSTPool", Thread.NORM_PRIORITY)).scheduleAtFixedRate(new Runnable() {
        @Override
        public void run() {
            throw new RuntimeException("Test Error");
        }
    },3000, 3000, TimeUnit.MILLISECONDS);

    while (true){}
}

Will print

java.lang.RuntimeException: Test Error
java.lang.RuntimeException: Test Error
java.lang.RuntimeException: Test Error
java.lang.RuntimeException: Test Error
java.lang.RuntimeException: Test Error

So your task will execute forever in spite of throwings error.

like image 38
ITurchenko Avatar answered Nov 21 '25 18:11

ITurchenko



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!