以下代码工作正常
abstract class FunctionRunnable<V> implements Runnable {
protected abstract V calculate();
private V result;
private Throwable thr;
public synchronized final void run() {
try {
result = calculate();
}
catch (Throwable thr) {
this.thr = thr;
}
}
public synchronized final V getResult() {
if (thr != null) {
throw new RuntimeException(thr);
}
return result;
}
}
...
final FunctionRunnable<Boolean> runnable = new FunctionRunnable<Boolean>() {
public Boolean calculate() {
return doCalculation();
}
private boolean doCalculation() {
...
}
});
SwingUtilities.invokeAndWait(runnable);
final Boolean resultObj = runnable.getResult();
final boolean result = resultObj.booleanValue();
直到Apple发布1.6.0_31,我们的应用程序的用户有时在最后一行获得了NPE。
您是否看到代码中存在错误,或者其他人是否发现此特定Java更新存在类似问题?
答案 0 :(得分:3)
我的SSCCE:
public abstract class FunctionRunnable<V> implements Runnable {
private V result;
private Throwable thr;
protected abstract V calculate();
public synchronized final void run() {
try { result = calculate(); } catch (Throwable thr) { this.thr = thr; }
}
public synchronized final V getResult() {
if (thr != null) throw new RuntimeException(thr);
return result;
}
public static void main(String[] args) throws Exception {
final FunctionRunnable<Boolean> runnable = new FunctionRunnable<Boolean>() {
public Boolean calculate() { return doCalculation(); }
private boolean doCalculation() {
try { Thread.sleep(2000); } catch (InterruptedException e) {}
return false;
}};
SwingUtilities.invokeAndWait(runnable);
System.out.println(runnable.getResult().booleanValue());
}
}
我的Java版本:
$java -version
java version "1.6.0_31"
Java(TM) SE Runtime Environment (build 1.6.0_31-b04-415-11M3635)
Java HotSpot(TM) 64-Bit Server VM (build 20.6-b01-415, mixed mode)
开始,跑了2秒,打印false
。
答案 1 :(得分:3)
如果你查看EventQueue.invokeAndWait的实现,你会发现它没有正确处理虚假的唤醒。它调用lock.wait()然后不检查runnable是否实际上已经完成执行 - 这意味着invokeAndWait可以在runnable执行完毕之前返回!
出于某种原因,在mac os上的更新31中以合理的频率开始虚假唤醒,暴露了EventQueue中的这个长期存在的错误。我不确定发生了什么变化,在任何其他版本的Java中都不会发生这种情况。
我们通过实现自己的invokeAndWait方法并使用简单的布尔检查来完成runnable来修复此问题。
答案 2 :(得分:1)
我有时会得到NullPonterExeption ......很奇怪
java版“1.6.0_31” Java(TM)SE运行时环境(版本1.6.0_31-b04-415-11M3635) Java HotSpot(TM)客户端VM(版本20.6-b01-415,混合模式)