How to restart a schedule when schedWithFixedDelay throws an exception?

I use ScheduledExecutorService to schedule some tasks that need to be run periodically. I want to know if this code works to restore the schedule when an exception occurs.

 ScheduledExecutorService service = Executors.newScheduledThreadPool(1); this.startMemoryUpdateSchedule(service);//See below method //Recursive method to handle exception when run schedule task private void startMemoryUpdateSchedule(ScheduledExecutorService service) { ScheduledFuture<?> future = service.scheduleWithFixedDelay(new MemoryUpdateThread(), 1, UPDATE_MEMORY_SCHEDULE, TimeUnit.MINUTES); try { future.get(); } catch (ExecutionException e) { e.printStackTrace(); logger.error("Exception thrown for thread",e); future.cancel(true); this.startMemoryUpdateSchedule(service); } catch(Exception e) { logger.error("Other exception ",e); } } 
+4
source share
4 answers

You should probably enclose a try block in a while(true) , because if the first run does not throw an exception, you will exit your method, and if the second call will call it, you will not catch it.

I would also run a recursive call on my thread to avoid the risk of a StackOverFlow error if things go wrong.

So it will look like this:

 private void startMemoryUpdateSchedule(final ScheduledExecutorService service) { final ScheduledFuture<?> future = service.scheduleWithFixedDelay(new MemoryUpdateThread(), 1, UPDATE_MEMORY_SCHEDULE, TimeUnit.MINUTES); Runnable watchdog = new Runnable() { @Override public void run() { while (true) { try { future.get(); } catch (ExecutionException e) { //handle it startMemoryUpdateSchedule(service); return; } catch (InterruptedException e) { //handle it return; } } } }; new Thread(watchdog).start(); } 
+1
source

Try using the VerboseRunnable class from jcabi-log , which is designed specifically for this purpose:

 import com.jcabi.log.VerboseRunnable; Runnable runnable = new VerboseRunnable( Runnable() { public void run() { // do business logic, may Exception occurs } }, true // it means that all exceptions will be swallowed and logged ); 

Now when someone calls runnable.run() , no exceptions are thrown. Instead, they are swallowed and recorded (for SLF4J).

+1
source

I added a loop as discussed.

 public void startMemoryUpdateSchedule(final ScheduledExecutorService service) { boolean retry = false; do { ScheduledFuture<?> future = null; try { retry = false; future = service.scheduleWithFixedDelay(new MemoryUpdateThread(), 1, UPDATE_MEMORY_SCHEDULE, TimeUnit.SECONDS); future.get(); } catch (ExecutionException e) { // handle future.cancel(true); retry = true; } catch(Exception e) { // handle } } while (retry); } 
0
source

ScheduledExecutorService.scheduleWithFixedDelay(Runnable, long, long, TimeUnit) throws RejectedExecutionException (child of RuntimeException) ==> We can catch it and try sending again.

Now that future.get() should return the result of one execution, we need to call it in a loop.

In addition, a failure of one execution does not affect the next scheduled execution, which distinguishes ScheduledExecutorService from TimerTask, which executes scheduled tasks in the same thread => failure in one execution would interrupt the schedule in case of TimerTask (http://stackoverflow.com / questions / 409932 / java-timer-vs-executorservice) We just need to catch all three exceptions thrown by Future.get (), but we won’t be able to recover them, then we won’t be able to get the result of subsequent executions.

The code may be:

 public void startMemoryUpdateSchedule(final ScheduledExecutorService service) { final ScheduledFuture<?> future; try { future = service.scheduleWithFixedDelay(new MemoryUpdateThread(), 1, UPDATE_MEMORY_SCHEDULE, TimeUnit.SECONDS); } catch (RejectedExecutionException ree) { startMemoryUpdateSchedule(service); return; } while (true) { try { future.get(); } catch (InterruptedException ie) { Thread.currentThread().interrupt(); } catch (ExecutionException ee) { Throwable cause = ee.getCause(); // take action, log etc. } catch (CancellationException e) { // safety measure if task was cancelled by some external agent. } } } 
0
source

Source: https://habr.com/ru/post/1415092/


All Articles