Когда поток собирается завершить работу из-за неперехваченного исключения, виртуальная машина Java запросит поток для его UncaughtExceptionHandler
, используя Thread.getUncaughtExceptionHandler (), и вызовет метод uncaughtException обработчика, передав поток и исключение в качестве аргументов. .
UncaughtExceptionHandler будет вызываться, если отправленная задача выдает неперехваченное исключение, но RejectionExecutionException
не вызывает саму задачу. Однако вы можете передать RejectedExecutionHandler
в ThreadPoolExecutor
.
public ThreadPoolExecutor(int corePoolSize,
int maximumPoolSize,
long keepAliveTime,
TimeUnit unit,
BlockingQueue<Runnable> workQueue,
RejectedExecutionHandler handler) {
this(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue,
Executors.defaultThreadFactory(), handler);
}
ThreadPoolExecutor принимает RejectedExecutionHandler
в качестве аргумента.
РЕДАКТИРОВАТЬ:
В вашем случае UncaughtExceptionHandler
не вызывается / не уведомляется, потому что при вызове scheduleWithFixedDelay
не выполняет ваш Runnable напрямую, однако он деформируется в ScheduledFutureTask
. Теперь, когда executor.submit(() -> Thread.sleep(10000));
выдает исключение (в вашем случае RejectionExecutionException), оно не остается необработанным, поскольку FutureTask#run
перехватило исключение и установило исключение как Будущий результат / результат. Посмотрите на часть метода FutureTask#run
:
try {
result = c.call();
ran = true;
} catch (Throwable ex) {
result = null;
ran = false;
setException(ex);
}
И setException()
, установленного для объекта исключения outcome
из FutureTask
.
protected void setException(Throwable t) {
if (UNSAFE.compareAndSwapInt(this, stateOffset, NEW, COMPLETING)) {
outcome = t;
UNSAFE.putOrderedInt(this, stateOffset, EXCEPTIONAL); // final state
finishCompletion();
}
}
Теперь вопрос, можем ли мы каким-то образом получить исключение / уведомление об Исключении?
Да, это возможно. Когда вы назовете Future#get
на будущее, будет сгенерировано исключение, однако Exception
будет заключено в ExecutionException
. Взгляните на метод Future#get
.
public V get() throws InterruptedException, ExecutionException {
int s = state;
if (s <= COMPLETING)
s = awaitDone(false, 0L);
return report(s);
}
@SuppressWarnings("unchecked")
private V report(int s) throws ExecutionException {
Object x = outcome;
if (s == NORMAL)
return (V)x;
if (s >= CANCELLED)
throw new CancellationException();
throw new ExecutionException((Throwable)x);
}
Я видел все доступные методы (отправить, выполнить, запланировать и т. Д.) На ScheduledThreadPoolExecutor
обернуть task
в будущем задании. Так что я думаю, что нет никакого способа быть в случае исключения через UncaughtExceptionHandler
.
Однако в случае ThreadPoolExecutor, если вы отправите задачу с помощью ThreadPoolExecutor#submit
, ваш UncaughtExceptionHandler
будет не уведомлен, но если вы используете ThreadPoolExecutor#execute
, UncaughtExceptionHandler
будет уведомлен какThreadPoolExecutor#execute
не включает вашу задачу в Future
.