You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

CompletableFuture.supplyAsync抛出IllegalMonitorStateException问题

结论

这个报错是预期行为,你的代码存在明确的写法疏漏。

错误原因
  • 核心异常来源是对Object.wait()方法的错误使用
    所有Java对象都继承了wait()、notify()、notifyAll()这三个方法,它们属于对象内置监视器机制的组成部分,调用wait()的硬性前提是当前线程必须持有该对象的synchronized监视器锁,未持有锁直接调用就会固定抛出IllegalMonitorStateException,和CompletableFuture任务是否完成没有任何关系。
    你看到输出里已经打印了Alarm:911,是因为异步任务执行速度很快,在主线程走到wait调用前就已经完成、触发了回调,但这不会消除wait方法本身的用法错误。
  • 混淆了API的适用场景
    wait()根本不是用来等待CompletableFuture任务完成的API,就算你给wait外层加了synchronized锁,也达不到预期效果——CompletableFuture任务完成时不会主动调用notify/notifyAll唤醒等待线程,你会直接阻塞住无法正常唤醒。
  • 存在隐藏的空指针风险
    你在whenComplete回调里没有判断error是否为null就直接调用error.printStackTrace(),当任务正常执行完成(比如你当前返回911的场景)时,error参数是null,这行代码会在异步线程中抛出空指针异常,只是因为你没有持有whenComplete返回的新CompletableFuture对象,异常没有被主线程感知到而已。
修正方案

等待CompletableFuture完成要使用它自带的阻塞API,同时修复回调的空指针问题:

  • 要获取任务返回值就用get()方法,它会阻塞直到任务完成,返回执行结果,需要处理受检异常;
  • 不需要返回值可以用join()方法,它同样会阻塞等待,抛出的是非受检异常,不需要显式声明捕获。

修正后的可运行代码:

public static void main(String[] args) throws Exception {
    CompletableFuture<Integer> future = CompletableFuture.supplyAsync(
      () -> { return 911; });
    future.whenComplete(
      (result, error) -> {
        System.out.println("Alarm:" + result);
        // 判空避免空指针
        if (error != null) {
            error.printStackTrace();
        }
      }
    );
    // 替换wait(),等待异步任务完成
    future.get();
}

运行这段代码就只会打印Alarm:911,不会有任何异常抛出。

内容的提问来源于stack exchange,提问作者Troskyvs

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.28 10:39:18