有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

爪哇猪笼草。invokeAndWait不等待?

下面的代码运行良好

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();

在苹果发布1.6.0_31之前,我们应用程序的用户有时会在最后一行获得NPE

您是否在代码中看到了bug,或者其他人是否发现了与此特定Java更新类似的问题


共 (3) 个答案

  1. # 1 楼答案

    我有时会被剥夺权利。。。。诡异的

    java版本“1.6.0_31” Java(TM)SE运行时环境(build 1.6.0_31-b04-415-11M3635) Java HotSpot(TM)客户端虚拟机(构建20.6-b01-415,混合模式)

  2. # 2 楼答案

    我的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

  3. # 3 楼答案

    如果您关注EventQueue的实现。invokeAndWait您将看到它无法正确处理虚假唤醒。它叫锁。wait()则不检查runnable是否实际完成了执行——这意味着invokeAndWait可以在runnable完成执行之前返回

    出于某种原因,mac os上的update 31开始以合理的频率出现虚假唤醒,暴露了EventQueue中这个长期存在的漏洞。我不确定发生了什么变化,这在任何其他版本的Java中都不会发生

    我们通过实现我们自己的invokeAndWait方法来解决这个问题,方法是对runnable的完成进行简单的布尔检查