我有以下类使用synchronized来尝试阻止对密钥的访问,直到生成密钥为止:
public class KeyManager {
private String key;
public KeyManager() {
genKey();
}
private void genKey() {
new Thread(new Runnable() {
synchronized(KeyManager.this) {
public void run() {
key = operationThatTakesALongTime();
}
}
}).start();
}
synchronized public String getKey() {
return key;
}
}
问题是getKey()有时会在内部线程之前被调用,并且它首先抓取锁。
我真正需要的是在getKey()中等待,只有在键为空时才等待。怎么做?
答案 0 :(得分:3)
MHM
synchronized public long getKey()
{
while (key == null)
{
try
{
wait();
}
catch(InterruptedException e)
{
/* handle here */
}
}
return key;
}
wait
会让线程释放锁,然后在调用notify
时再次使用它。如果key仍为null,则会再次释放锁定。
但我认为这不是最好的方法。
抛出InterruptedException
。
答案 1 :(得分:2)
我会使用CountDownLatch
而不是重新实现逻辑。
我也可能避免从构造函数中启动一个新的Thread,因为它可能会导致细微的并发错误 - 相反,您可以简单地将genKey
方法设为public并添加相关的javadoc(此方法必须首先调用布拉布拉):
public class KeyManager {
private volatile boolean genStarted = false;
private final CountDownLatch keyGenerated = new CountDownLatch(1);
private String key;
public void genKey() {
genStarted = true;
new Thread(new Runnable() {
public void run() {
key = operationThatTakesALongTime();
keyGenerated.countDown();
}
}).start();
}
public String getKey() throws InterruptedException {
if (!genStarted) throw new IllegalStateException("you must run genKey first");
keyGenerated.await();
return key;
}
}