我想在 Java EE 中实现一个单例 bean,它可以按需启动 VPN 连接。
因此,我创建了一个类,如:
@Singleton
class VPNClient{
private boolean connected;
@Lock(LockType.READ)
public boolean isConnected(){
return this.connected;
}
@Asynchronous
@Lock(LockType.WRITE)
public void connect(){
// do connect, including a while loop for the socket:
while(true){
// read socket, do stuff like setting connected when VPN successfully established
}
}
}
然后我有另一个 bean,它需要 VPN 连接并尝试创建它:
class X {
@Inject
VPNClient client;
private void sendStuffToVPN(){
// call the async connect method
client.connect();
// wait for connect (or exception and stuff in original source)
while(!client.isConnected()){
// wait for connection to be established
Thread.sleep(5000);
}
}
}
我现在的问题是,由于连接方法,在连接被破坏之前永远不会结束,它拥有的写锁将阻止所有对 isConnected() 的读取。
[更新]
这应该有望说明问题:
- 线程 1 (Bean X) 调用线程 2 (Singleton Bean VPNClient) .connect()
- 现在单例 bean VPNClient 上有一个无限写锁。但是因为该方法被称为异步。线程 1 继续:
- 线程 1 (Bean x) 尝试调用线程 2 (VPNClient.isConnected()),但必须等待写锁的释放(从 connect() 开始)。
- 然后 J2EE 容器抛出 javax.ejb.ConcurrentAccessTimeoutException,因为它一直等到超时。
有没有解决这种并发问题的好模式?