在我的Singleton-EJB中,我每2分钟启动一个TimerService。当客户端访问测试方法 有时应用程序会陷入死锁。问题是,该测试方法调用EJB(参见方法determineABC)内的异步方法。当scheduleMethod尝试创建单个操作计时器并因此尝试获取锁(因为hte timer回调方法用LOCK.WRITE注释)时发生死锁。同时,我们已经在尝试调用asynchMethod异步方法determineABC方法。也许电话ejbLocal.asynchMethod(...);也试图获得一个锁。无论如何,我遇到了一个死锁,因为异步方法从来没有被调用过。那么问题是什么?DEADLOCK,具有异步方法的EJB 3.1和Singleton中的TimerService
这里是源代码片段:
@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);
}
死锁也发生在我只用@Schedule方法,没有TimerService ... 僵局也发生在我不使用Future对象,但是作为异步方法的返回类型无效。
当超时异常被抛出的僵局得到解决。当我注释计时器方法与@AccessTimeout(2000)和这个时间已到的异步方法被调用,因此,死锁也得到解决。
当我使用Locktype.READ为定时器方法没有死锁发生。但为什么?异步方法调用什么?