简体   繁体   English

简单的 CompletableFuture.supplyAsync() 导致 IllegalMonitorStateException 错误

[英]Simple CompletableFuture.supplyAsync() leads to IllegalMonitorStateException error

I'm trying this in java8:我在java8中尝试这个:

  public static void main(String[] args) throws Exception {
    CompletableFuture<Integer> future = CompletableFuture.supplyAsync(
      () -> { return 911; });
    future.whenComplete(
      (result, error) -> {
        System.out.println("Alarm:" + result);
        error.printStackTrace();
      }
    );
    future.wait();
  }

Upon running, I got this output:运行后,我得到了这个输出:

Alarm:911
[WARNING]
java.lang.IllegalMonitorStateException
    at java.lang.Object.wait (Native Method)
    at java.lang.Object.wait (Object.java:502)
    at mygroup.UseCompletableFuture.main (UseCompletableFuture.java:15)
    at org.codehaus.mojo.exec.ExecJavaMojo$1.run (ExecJavaMojo.java:254)
    at java.lang.Thread.run (Thread.java:748)

Is the "error" information expected?是否需要“错误”信息? Did I miss anything in my code snippet?我错过了代码片段中的任何内容吗?

The wait method derives from the Object class. wait方法派生自Object类。 If you need to use it, you need to monitor the object.如果你需要使用它,你需要监控对象。

In your case, you should not need to monitor, but you need to 'wait for the completable future to complete'.在您的情况下,您不需要监控,但您需要“等待可完成的未来完成”。 In this case you need to switch from wait to get method.在这种情况下,您需要从wait切换到get方法。

The exception whose stack trace is shown is thrown by future.wait() and is not related to the error argument of the second CompleableFuture .显示堆栈跟踪的异常由future.wait()抛出,并且与第二个CompleableFutureerror参数无关。 It occurs because wait() requires the thread invoking it to be holding the object's monitor.这是因为wait()要求调用它的线程持有对象的监视器。 See this for a description of what it means for a thread to be owner of the object's monitor.有关线程成为对象监视器的所有者意味着什么的描述,请参阅this Your code basically has to be within a synchronized block in order to be able to call wait() or notify() .您的代码基本上必须在synchronized块内才能调用wait()notify() You probably intended to call get() , the wait()/notify() methods are generic synchronization methods inherited by Object and have been there since the beginning of Java.您可能打算调用get()wait()/notify()方法是由Object继承的通用同步方法,并且从 Java 开始就一直存在。

As for the error parameter, it is indeed null, because the first stage completes normally.至于error参数,确实是null,因为第一阶段正常完成。 Hence, the line error.printStackTrace() should thrown a NPE.因此, error.printStackTrace()行应该抛出一个 NPE。 However, your code simply does not handle.但是,您的代码根本无法处理。 It is thrown in the async thread that executes the stage, and remains silent.它被抛出在执行阶段的异步线程中,并保持沉默。 See this post in relation to this behavior.有关此行为,请参阅此帖子

I suspect you want to call the get() method on the future.我怀疑你想在未来调用get()方法。 First you should assign the second stage to a variable ( future is still referencing the first stage):首先,您应该将第二阶段分配给一个变量( future仍然引用第一阶段):

future = future.whenComplete(
      (result, error) -> {
        System.out.println("Alarm:" + result);
        System.out.println(error);
        error.printStackTrace();
      }
);

Then you could call get() on it, which allows you to handle an ExecutionException which will wrap the NPE occurring in the second stage:然后你可以在它上面调用get() ,它允许你处理一个ExecutionException ,它将包装在第二阶段发生的 NPE:

try {
    result = future.get();
    System.out.println(result);
} catch (InterruptedException e) {
    ...
} catch (ExecutionException e) {
    ...
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM