开发者

ScheduledExecutorService throwable lost

Consider I scheduled a Runnable for periodic execution with ScheduledExecutorService and there occurs some system Error like OutOfMemory. It will be silently swallowed.

scheduler.scheduleWithFixedDelay(new Runnable() {
                    @Override
                    public void run() {
   开发者_如何学Go                   throw new OutOfMemoryError(); // Swallowed
                    }
                }, 0, delay, TimeUnit.SECONDS);

Is it normal?

Why doesn't it propagate to the container?

What is the correct way to handle such errors?

Thanks!


An OutOfMemoryError, like any subtype of Error, cannot be recovered from, they're generally fatal to your program. It doesn't really matter if you try and catch it or not, your program's going down.

If, however, you mean an Exception rather than an Error, then you have 2 options:

  1. Catch the exception from within your task's run() method.
  2. Call get() on the Future() returned by scheduleWithFixedDelay(). This will propagate the exception back to the submitting thread, but it will block until that happens.


The method will return a ScheduledFuture instance, which get methods (with or without a timeout) will throw an ExecutionException with your OutOfMemoryError as cause.


The ListenableFuture class from guava may be useful here.

With this you can create an exception handler task that logs the error then attempts to restart the failed task.

You still need a sleeping thread to watch for exceptions, but you only need one global exception handler thread for the whole process (rather than one for each scheduled task.)


Personally I would give your object sone kind of mechanism to report exceptions, rather than expect a framework to handle them. Think of an exception listener or similar.

For an oom, there is little you can do.

These executors ate there to execute your stuff not to handle all the possible problems that your code may have!


You can use VerboseRunnable class from jcabi-log, which catches all exceptions and logs them:

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 anybody calls runnable.run() no exceptions are thrown. Instead, they are swallowed and logged (to SLF4J).

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜