Asynchronous 死锁,EJB3.1,在Singleton中使用异步方法和TimerService

Asynchronous 死锁,EJB3.1,在Singleton中使用异步方法和TimerService,asynchronous,jakarta-ee,deadlock,ejb-3.1,Asynchronous,Jakarta Ee,Deadlock,Ejb 3.1,在我的单例EJB中,我每2分钟启动一次TimerService。当客户端访问测试方法时 有时应用程序会陷入死锁。问题是,test方法调用EJB内部的异步方法(请参见方法determinateABC)。当scheduleMethod尝试创建单个动作计时器并因此尝试获取锁时,就会发生死锁(因为计时器回调方法是用lock.WRITE注释的)。同时,我们已经使用了determiniabc方法,该方法试图调用异步方法asynchMethod。可能是调用ejbLocal.asynchMethod(…)还尝试

在我的单例EJB中,我每2分钟启动一次TimerService。当客户端访问测试方法时 有时应用程序会陷入死锁。问题是,test方法调用EJB内部的异步方法(请参见方法determinateABC)。当scheduleMethod尝试创建单个动作计时器并因此尝试获取锁时,就会发生死锁(因为计时器回调方法是用lock.WRITE注释的)。同时,我们已经使用了determiniabc方法,该方法试图调用异步方法asynchMethod。可能是调用ejbLocal.asynchMethod(…)还尝试获取锁。无论如何,在这里我遇到了死锁,因为异步方法从未被调用。那么问题是什么呢

以下是源代码片段:

@Singleton
@Startup
@TransactionManagement(TransactionManagementType.CONTAINER)
@TransactionAttribute(TransactionAttributeType.NOT_SUPPORTED)
@ConcurrencyManagement(ConcurrencyManagementType.CONTAINER)
public class XEJB implements XEJBLocal {

@javax.annotation.Resource(name = "x/XEJB/TimeService")
private TimerService timerService;
@javax.annotation.Resource
private SessionContext ctx;

@Schedule(minute = "*/2", hour = "*", persistent = false)
@Lock(LockType.READ)
private void scheduleMethod() {
    // Create Single Action Timer
    timerService.createSingleActionTimer(new Date(), new TimerConfig(null, false));
}

@Timeout
@Lock(LockType.WRITE)
private void timer(Timer timer) {
   // Do something
}

@Override
@Lock(LockType.READ)
public B test(...)  {
    return determineABC(...);
}

@Lock(LockType.READ)
private B determineABC(...) {
    XEJBLocal ejb= (XEJBLocal)  ctx.getBusinessObject(ctx.getInvokedBusinessInterface());
    Future<ArrayList> result = null;
    result = ejb.asynchMethod(...);
    result.get(4, TimeUnit.MINUTES);  // Sometimes runs into a DEADLOCK
    ...
}

@Asynchronous
@Override
@Lock(LockType.READ)
public Future<ArrayList> asynchMethod(...) {
    ...
    return new AsyncResult<ArrayList>(abcList);
}
@Singleton
@启动
@TransactionManagement(TransactionManagementType.CONTAINER)
@TransactionAttribute(不支持TransactionAttribute类型)
@ConcurrencyManagement(ConcurrencyManagementType.CONTAINER)
公共类XEJB实现了XEJBLocal{
@javax.annotation.Resource(name=“x/XEJB/TimeService”)
私人TimerService TimerService;
@javax.annotation.Resource
私人会话上下文ctx;
@时间表(分钟=“*/2”,小时=“*”,持续=假)
@锁(LockType.READ)
私有void scheduleMethod(){
//创建单动作计时器
createSingleActionTimer(new Date(),new TimerConfig(null,false));
}
@超时
@锁(LockType.WRITE)
专用无效计时器(计时器){
//做点什么
}
@凌驾
@锁(LockType.READ)
公共B检验(…){
返回确定性c(…);
}
@锁(LockType.READ)
私有B可确定性c(…){
XEJBLocal ejb=(XEJBLocal)ctx.getBusinessObject(ctx.getInvokedBusinessInterface());
未来结果=空;
结果=ejb.asynchMethod(…);
result.get(4,TimeUnit.MINUTES);//有时会遇到死锁
...
}
@异步的
@凌驾
@锁(LockType.READ)
公共未来异步方法(…){
...
返回新的异步结果(abcList);
}
当我只使用@Schedule方法而不使用TimerService时,也会发生死锁。。。 当我不使用Future对象而是void作为异步方法的返回类型时,也会发生死锁

当抛出超时异常时,死锁被解决。当我用@AccessTimeout(2000)注释timer方法时,此时将调用异步方法,因此死锁也被解决


当我对计时器方法使用Locktype.READ时,不会发生死锁。但是为什么?异步方法调用什么?

读取锁必须等待写入锁完成后才能开始工作。当timer()时正在工作的所有其他调用,即使是读取方法,都将等待。是否确定超时发生在
result.get(4,TimeUnit.MINUTES);


我认为您可能在test()调用中有访问超时,在到达
结果之前。get(4,TimeUnit.MINUTES);
读锁必须等待写锁完成后才能开始工作。当timer()时正在工作的所有其他调用,即使是读取方法,都将等待。是否确定超时发生在
result.get(4,TimeUnit.MINUTES);

我认为在到达
result.get(4,TimeUnit.MINUTES);
之前,您可能在test()调用中有访问超时