2

次のコードは正常に機能しました

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アップデートで同様の問題を見つけましたか?

4

3 に答える 3

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

于 2012-05-25T10:31:05.327 に答える
3

EventQueue.invokeAndWaitの実装を調べると、誤ったウェイクアップを正しく処理していないことがわかります。次にlock.wait()を呼び出し、ランナブルが実際に実行を終了したかどうかをチェックしません。これは、ランナブルが実行を終了する前に、invokeAndWaitが戻ることができることを意味します。

何らかの理由で、Mac OSのアップデート31で、スプリアスウェイクアップが妥当な頻度で発生し始め、EventQueueのこの長年のバグが明らかになりました。何が変わったのかわかりません。他のバージョンのJavaでは起こりません。

ランナブルの完了を確認する単純なブールチェックを使用して独自のinvokeAndWaitメソッドを実装することで、これを修正しました。

于 2012-06-11T23:27:42.653 に答える
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、混合モード)

于 2012-05-28T11:21:42.090 に答える