SwingUtilities.invokeAndWait不等待?

时间:2012-05-25 10:21:28

标签: java multithreading macos swing

以下代码工作正常

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更新存在类似问题?

3 个答案:

答案 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,混合模式)