2011-01-12 4 views
2

Рассмотрите, что я запланировал Runnable для периодического выполнения с помощью ScheduledExecutorService и возникает некоторая системная ошибка, например OutOfMemory. Он будет молча проглочен.ScheduledExecutorService throwable lost

scheduler.scheduleWithFixedDelay(new Runnable() { 
        @Override 
        public void run() { 
         throw new OutOfMemoryError(); // Swallowed 
        } 
       }, 0, delay, TimeUnit.SECONDS); 

Нормально ли это?

Почему он не распространяется на контейнер?

Каков правильный способ обработки таких ошибок?

Спасибо!

ответ

2

OutOfMemoryError, как и любой подтип Error, не могут быть восстановлены, они, как правило, являются фатальными для вашей программы. Не имеет значения, пытаетесь ли вы его поймать или нет, ваша программа идет вниз.

Если, однако, вы имеете в виду в Exception, а не Error, то у вас есть 2 варианта:

  1. поймать исключение из run() в методе вашей задачи.
  2. Звоните get() на номер Future(), указанный scheduleWithFixedDelay(). Это будет распространять исключение обратно на подающий поток, но он будет блокироваться до тех пор, пока это не произойдет.
1

Метод возвращает экземпляр ScheduledFuture, который получает методы (с тайм-аутом или без него) будет генерировать ExecutionException с вашим OutOfMemoryError в качестве причины.

+0

Итак, вы советуете всегда вызывать future.get() после планирования повторяемой задачи? Но это вызовет создание спальных нитей. Это нормально? –

+1

Ну, вы не можете знать, выбрала ли ваша работа исключение или нет до тех пор, пока оно не будет завершено, поэтому вам придется подождать, пока он завершится успешно или не сработает (выбросьте исключение или ошибку).Если вы вызываете get с тайм-аутом 0, метод будет вызывать исключение TimeoutException, если задание все еще выполняется. Вам не нужно блокировать поток, чтобы запросить статус возвращенного Будущего. – jarnbjo

0

Категория ListenableFuture от guava может быть здесь полезной.

С помощью этого вы можете создать задачу обработчика исключений, которая регистрирует ошибку, а затем пытается перезапустить неудачную задачу.

Вам все еще нужен спящая нить, чтобы наблюдать за исключения, но вам нужно только один глобальный обработчик исключений потока для всего процесса (а не по одному для каждой запланированной задачи.)

0

Лично я отдал бы свой объект Соня вида механизма отчетности об исключениях, а не ожидать, что они будут работать с ними. Подумайте о прослушивании исключений или о подобном.

Для oom, вы можете сделать немного.

Эти исполнители съели там, чтобы выполнить ваши вещи, чтобы не справляться со всеми возможными проблемами, которые могут возникнуть у вашего кода!

0

Вы можете использовать VerboseRunnable класс от jcabi-log, который перехватывает все исключения и регистрирует их:

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 
); 

Теперь, когда кто-нибудь называет runnable.run() исключения не выбрасываются. Вместо этого они проглатываются и регистрируются (до SLF4J).

Смежные вопросы