Jakarta ee @Singleton EJB中的多个计时器抛出javax.EJB.ConcurrentAccessTimeoutException

Jakarta ee @Singleton EJB中的多个计时器抛出javax.EJB.ConcurrentAccessTimeoutException,jakarta-ee,timer,ejb,Jakarta Ee,Timer,Ejb,我有一个调度单例,我试图管理多个日历计时器。我每30分钟打一次电话。但是,每天一次(例如凌晨3点),我需要打电话给同一个服务来做一些不同的事情 主要问题-在同一个单例中可以有多个计时器吗 当我看代码时,我觉得在某个时刻(凌晨3点),两个计时器会发生冲突,我会得到一个ConcurrentAccessTimeoutException,其中一个不会运行。例如: Caused by: javax.ejb.ConcurrentAccessTimeoutException: WFLYEJB0241: EJB

我有一个调度单例,我试图管理多个日历计时器。我每30分钟打一次电话。但是,每天一次(例如凌晨3点),我需要打电话给同一个服务来做一些不同的事情

主要问题-在同一个单例中可以有多个计时器吗

当我看代码时,我觉得在某个时刻(凌晨3点),两个计时器会发生冲突,我会得到一个ConcurrentAccessTimeoutException,其中一个不会运行。例如:

Caused by: javax.ejb.ConcurrentAccessTimeoutException: WFLYEJB0241: EJB 3.1 PFD2 4.8.5.5.1 concurrent access timeout on TestBean- could not obtain lock within 5000MILLISECONDS
也许如果我在施工后首先创建凌晨3点计时器,它将更有可能运行并锁定every30计时器?但即使这是可能的,它似乎是一个)小傻瓜b)让事情的机会。我可以忍受every30定时器在凌晨3点不运行,但不能错过单次运行,因为这是它唯一运行的时间。另一个选择是将every30计时器设置为不会与每天一次计时器同时运行的时间,但再次设置为hokey

这是我的密码:

@Singleton
@Startup
@TransactionManagement(TransactionManagementType.CONTAINER)
@TransactionAttribute(TransactionAttributeType.NOT_SUPPORTED)
public class SomeScheduler
{

   @Resource
   private TimerService timerService;   
   
   @Inject
   @ConfiguredProperty(key="scheduleExpression1", mandatory=false, defaultValue="minute=*/30; hour=*")
   private ScheduleExpression scheduleExpression1;   
   
   @Inject
   @ConfiguredProperty(key="scheduleExpression2", mandatory=false, defaultValue="hour=3; dayOfWeek=*")
   private ScheduleExpression scheduleExpression2;      
   
   private Timer timer1;
   private Timer timer2;
   
   
   @PostConstruct
   private void postConstruct()
   {
     timer1 = timerService.createCalendarTimer(scheduleExpression1, new TimerConfig("every30", false));
     timer2 = timerService.createCalendarTimer(scheduleExpression2, new TimerConfig("at3AM", false));
   }
      
   @Timeout
   public void handler (Timer timer) 
   { 
     if (Objects.equals(timer.getInfo(), "every30"))            
     {
        // Call Something
     }
     if (Objects.equals(timer.getInfo(), "at3AM"))
     {
        // Call Something else
     }
   } 

}

是的,您可以在同一个单例中有多个计时器。
但您必须关闭“容器管理的并发访问”,方法是使用以下内容注释您的单例:

@ConcurrencyManagement(ConcurrencyManagementType.BEAN)

默认情况下,
@Singleton
bean中的公共方法具有
@Lock(WRITE)
。如果您需要在同一时间多次运行同一方法,并且您在竞争条件下是安全的,那么您可以在方法顶部添加注释
@Lock(READ)

如果您在这种特定方法中使用竞争条件不安全,则可以通过注释增加访问超时:
@AccessTimeout


这将解决ConcurrentAccessTimeoutException。

任务是否冲突且不能同时运行?您可以放松并发限制,或者您也可以设置更大的超时,以便在两个任务发生冲突时,可以等待它们发生冲突。作为实验,将计时器1设置为每两分钟运行一次,计时器2设置为每10分钟运行一次。在10分钟的时候,TIMER2启动了,我收到了几个与TIMER1相关的ConcurrentAccessTimeoutException消息。我将尝试将AccessTimeout设置为更大的值,看看这是否有帮助。我的部分问题是,在同一个类中使用多个计时器是否被认为是不好的做法?如果使用默认的单例并发管理,则无法并行处理超时。因此,您需要设置一个足够的超时,以便运行任务结束,或者使用“-1”。如果您的任务可以在parelel中运行,您可以使用
@Lock(READ)