2014-02-20 2 views
7

Это реальная простая проблема, я думаю, но я не могу понять, почему так происходит. У меня есть реализация таймера 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 параллельного доступа таймаут на орг. [email protected] - не смог получить замок в 5000 миллисекунды

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

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


EDIT

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

@ 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()); 
} 

ответ

6

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

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

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

Во-вторых, то, что сделка с «не удалось получить блокировку в 5000MILLISECONDS» и как я могу избежать этого?

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

+1

@ Tushar-46835, можете ли вы рассказать о своем решении, может быть, показать нам фрагмент того, что вы сделали? – rtcarlson

+0

@rtcarlson: Вот фрагмент кода, который исправил мои проблемы: Ресурс TimerService timerService; Расписание (постоянная = ложь, минута = "*/30", час = "*") \t общественного недействительными checkQueueState() { \t \t дт = новый DataAccessFactory(); \t \t excvo = dt.canExecute(); \t \t dt = null; \t \t available = excvo.isExecuteReady(); \t \t если (есть) { \t \t \t timerService.createSingleActionTimer (новая дата(), новый TimerConfig ( \t \t \t \t \t нуль, ложь)); \t \t} \t} \t Timeout \t частный аннулируются generateReport (таймер Timer) { \t \t logger.info ("!! - время ожидания вызова здесь" + новый Date()); \t} – TusharPanda

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