Таймер создает несколько экземпляров таймера

Это очень простая проблема, я думаю, но я не могу понять, почему так происходит. У меня есть реализация таймера EJB, который использует аннотацию @Singleton, т.е. одноэлементный таймер.

Я установил его запускать каждые 5 минут. Код выглядит примерно так:

@Singleton
@TransactionAttribute(TransactionAttributeType.NOT_SUPPORTED)
public class Scheduler {
    private static final double timerVar = Math.random() * 33;

    static Logger logger = Logger.getLogger("Scheduler");

    @Schedule(second = "*", minute = "*/5", hour = "*", persistent = true)
    public void doWork() {
        logger.log(Level.INFO, "timer value for this session : " + timerVar);
    } 
}

Когда процесс запускается, он выполняет одновременно 10 экземпляров планировщика с интервалом в 1 секунду, т.е.

(EJB default - 1)
(EJB default - 2)
(EJB default - 3)
(EJB default - 4)

и так далее. Когда я помещаю длинную операцию в коде, (EJB default - 1) не завершена, и когда (EJB default - 2) пытается выполнить это дает мне ошибку, говоря:

JBAS014373: EJB 3.1 PFD2 4.8.5.5.1 тайм-аут одновременного доступа на org.jboss.invocation.InterceptorContext$Invocation@1b83ad52 - не удалось получить блокировку в течение 5000 МИЛЛИСЕКОНД

Во-первых, как можно избежать одновременного выполнения нескольких экземпляров планировщика EJB? Во-вторых, как обстоят дела с "не удалось получить блокировку в течение 5000 МИЛЛИСЕКОНД" и как мне ее избежать?

Для ошибки тайм-аута я обнаружил, что в очереди JBOSS много билетов, как упомянуто здесь.


РЕДАКТИРОВАТЬ

Добавлен код в последнем комментарии, чтобы его можно было прочитать:

@ Tushar-46835, не могли бы вы рассказать о своем решении, может, покажите нам фрагмент того, что вы сделали? - rtcarlson 2 октября '14 в 20:12

@rtcarlson: Вот фрагмент кода, который исправил мои проблемы:

 @Resource 
 TimerService timerService; 

 @Schedule(persistent = false, minute = "/30", hour = "") 
 public void checkQueueState() { 
     dt    = new DataAccessFactory(); 
     excvo = dt.canExecute(); 
     dt    = null; 
     available = excvo.isExecuteReady(); 
     if (available) { 
         timerService.createSingleActionTimer(new Date(), new TimerConfig(null, false)); 
     } 
 } 

 @Timeout 
 private void generateReport(Timer timer) {
     logger.info("!!--timeout invoked here " + new Date()); 
 }

1 ответ

Решение

Во-первых, как можно избежать одновременного выполнения нескольких экземпляров планировщика EJB?

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

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

Во-вторых, как обстоят дела с "не удалось получить блокировку в течение 5000 МИЛЛИСЕКОНД" и как мне ее избежать?

Это одноэлементный, все методы имеют запись типа блокировки по умолчанию, поэтому одновременно будет выполняться только один поток. Поэтому другие получат исключение тайм-аута / не смогут получить блокировку и т. Д. Как вы сказали, процесс выполняется долго.

Другие вопросы по тегам