Таймер создает несколько экземпляров таймера
Это очень простая проблема, я думаю, но я не могу понять, почему так происходит. У меня есть реализация таймера 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 МИЛЛИСЕКОНД" и как мне ее избежать?
Это одноэлементный, все методы имеют запись типа блокировки по умолчанию, поэтому одновременно будет выполняться только один поток. Поэтому другие получат исключение тайм-аута / не смогут получить блокировку и т. Д. Как вы сказали, процесс выполняется долго.