我将此EJB部署到Glassfish 4(Java EE 7):
import javax.ejb.EJB;
import javax.ejb.Lock;
import javax.ejb.LockType;
import javax.ejb.Schedule;
import javax.ejb.Singleton;
@Singleton
@Lock(LockType.WRITE) // WRITE is default, but here for emphasis
public class SingletonBean {
@EJB
SingletonBean self;
@Schedule(second="*/3", minute="*", hour="*")
public void test_automatic_timer() throws InterruptedException {
System.out.println("test_automatic_timer()");
self.test();
}
public void test() {
System.out.println("test()");
}
}
我预计这会陷入僵局。当计时器调用test_automatic_timer
时,它获得WRITE锁。对self.test()
的调用应该永远等待锁定被释放,但是在日志中我有:
Info: test_automatic_timer()
Info: test()
Info: test_automatic_timer()
Info: test()
为什么这不按我预期的方式工作?
P.S。这不完全是学术性的。我想进行self
调用,以便获得a new container-managed transaction,但我想确保首先更好地理解同步。
@Schedule(second="*/3", minute="*", hour="*")
public void test_automatic_timer() throws InterruptedException {
System.out.println("test_automatic_timer()");
System.out.println(Thread.currentThread());
self.test();
Thread.sleep(10_000);
}
@Asynchronous
public void test() {
System.out.println("test()");
System.out.println(Thread.currentThread());
}
如果这按预期工作,对test
的异步调用将被阻止十秒钟,直到test_automatic_timer
完成。如果它不起作用,test
将立即执行。日志显示:
Info: test_automatic_timer()
Info: Thread[__ejb-thread-pool11,5,main]
// 10 second pause...
Info: test()
Info: Thread[__ejb-thread-pool12,5,main]
所以它有效。
答案 0 :(得分:1)
此代码不会死锁,因为test()
的调用是在同一个(定时器执行)线程中进行的。
那就是说我认为至少有一些自我注入像这样的单身的行为可能是未定义的。如果您引入引用@PostConstruct
的{{1}}方法,会发生什么?
你的bean名称用词不当,因为self
bean是有状态的。
无论如何,做以下事情可能更安全:
@Singleton
这确实是使用新事务自我调用EJB的方法。