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

当进程运行时,它在 1 秒的间隔内同时执行 10 个调度程序实例,即

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

等等。当我在代码中放置一个冗长的操作时,(EJB default - 1)它并不完整,当(EJB default - 2)尝试执行它时给我一个错误提示:

JBAS014373:org.jboss.invocation.InterceptorContext$Invocation@1b83ad52 上的 EJB 3.1 PFD2 4.8.5.5.1 并发访问超时 - 无法在 5000 毫秒内获得锁定

首先,如何避免一次执行多个 EJB 调度程序实例?第二,“无法在 5000MILLISECONDS 内获得锁”是怎么回事,如何避免?

对于我得到的超时错误,我发现 JBOSS 队列中有很多票,如此处所述


编辑

在最新评论中添加了代码,以便阅读:

@Tushar-46835,您能否详细说明您的解决方案,或者向我们展示您所做的事情的片段?– rtcarlson 2014 年 10 月 2 日 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()); 
 }
4

1 回答 1

6

首先,如何避免一次执行多个 EJB 调度程序实例?

您正在创建持久计时器。因此,在指定的时间间隔之后,它将创建新的并将它们排入队列,等待前一个完成执行。

我想,在您重新启动后,所有排队的计时器都已超时,并且服务器将创建多个实例,因为它们是持久的。

第二,“无法在 5000MILLISECONDS 内获得锁”是怎么回事,如何避免?

它是单例的,所有方法默认都有锁类型的写入,所以一次只会执行一个线程。因此,其他人会得到超时异常/无法获得锁等。正如你所说,有一个长时间运行的过程。

于 2014-02-20T06:45:20.043 回答