2010-08-16 71 views
2

在我的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为定时器方法没有死锁发生。但为什么?异步方法调用什么?

回答

0

读锁等待写锁来完成他们开始他们的工作之前。当timer()工作时,所有其他调用(即使是读取方法)都将等待。你确定超时发生在result.get(4, TimeUnit.MINUTES);

我想你可能是在测试访问超时()invokation,达到result.get(4, TimeUnit.MINUTES);之前的方式。