我想在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);
}
}
}
我现在的问题是,由于connect方法,在连接被销毁之前永远不会结束,它所具有的写锁定将阻止对isConnected()的所有读取。
[更新]
这应该有希望说明问题:
有没有一种好的模式可以解决这种并发问题?
答案 0 :(得分:0)
@ Lock(LockType.WRITE)锁定单例bean中的所有方法,直到被调用的方法完成,即使调用者已经通过@Asynchronous进行了移动。
如果你考虑这是正确的行为 - 如果处理仍在进行中,则可以通过对bean的其他方法调用发生并发问题。
解决这个问题的方法是在你的单例上设置@ConcurrencyManagement(ConcurrencyManagementType.BEAN)来自己处理并发和锁定对连接的访问。
查看http://docs.oracle.com/javaee/6/tutorial/doc/gipvi.html#indexterm-1449的介绍。
答案 1 :(得分:-1)
试试这个。
class X {
private void sendStuffToVPN(){
VPNClient client = new VPNClient();
// call the async connect method
new Thread(new Runnable(){
public void run()
{
client.connect();
}
}).start();
// wait for connect (or exception and stuff in original source)
while(!client.isConnected()){
// wait for connection to be established
Thread.sleep(5000);
}
}
}