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

如何获取Task的void类型onComplete()方法的执行结果?

如何正确获取异步Task的执行结果

首先咱们先理清你之前踩坑的根源:

  • 直接调用mytask.wait()抛出IllegalMonitorStateException,是因为**wait()要求当前线程必须先持有该对象的锁**,你得先通过synchronized(mytask)获取锁才能调用,但更关键的是,如果这个库的Task内部没有在完成时调用notify()/notifyAll(),就算加了锁也会一直阻塞,所以这种方法根本不靠谱。
  • 用while(!mytask.isComplete()){}的忙等方式,会让你的线程一直占用CPU循环检查状态,要是在UI线程里这么干,直接就会导致界面完全冻结——因为UI线程没时间处理用户交互和界面绘制了。

接下来给你两种靠谱的解决方案,按需选择:

方案1:遵循库的异步回调设计(推荐)

这个库的Task本身就是为异步场景设计的——用onComplete()和onFail()回调来处理结果,所以最合理的方式是把你需要用结果做的逻辑直接放到回调里,而不是强行同步返回:

// 假设你的结果类型是ResultType
mytask.onComplete(() -> {
    // 在这里处理任务成功的结果
    ResultType result = getTaskResult(); // 替换成你获取结果的实际逻辑
    updateUI(result); // 比如更新界面
    doSomethingElseWithResult(result); // 或者调用其他业务方法
});

mytask.onFail(() -> {
    // 处理任务失败的情况
    showErrorToast("任务执行失败");
    handleTaskFailure();
});

这种方式完全符合库的设计初衷,不会有线程阻塞或冻结的问题,也是异步编程的常规做法。

方案2:用同步工具类强制同步获取结果(仅适用于非UI线程)

如果你确实需要在某个同步方法里拿到结果才能继续执行(比如后台线程的业务逻辑),可以用CountDownLatch来实现安全的等待,它不会像忙等那样浪费CPU:

import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
import java.util.concurrent.atomic.AtomicReference;

// 初始化一个计数为1的CountDownLatch
CountDownLatch latch = new CountDownLatch(1);
// 用AtomicReference来线程安全地保存结果和异常
AtomicReference<ResultType> taskResult = new AtomicReference<>();
AtomicReference<Exception> taskError = new AtomicReference<>();

mytask.onComplete(() -> {
    taskResult.set(getTaskResult()); // 保存成功结果
    latch.countDown(); // 计数减1,通知等待的线程
});

mytask.onFail(() -> {
    taskError.set(new RuntimeException("任务执行失败")); // 保存失败信息
    latch.countDown(); // 同样通知等待的线程
});

try {
    // 等待任务完成,最多等待10秒(可根据需求调整超时时间)
    if (latch.await(10, TimeUnit.SECONDS)) {
        if (taskError.get() != null) {
            // 任务失败,抛出异常或处理错误
            throw taskError.get();
        }
        // 任务成功,返回结果
        return taskResult.get();
    } else {
        // 超时处理
        throw new TimeoutException("任务执行超时");
    }
} catch (InterruptedException e) {
    // 等待被中断,恢复线程中断状态并抛出异常
    Thread.currentThread().interrupt();
    throw new RuntimeException("等待任务完成时被中断", e);
}

为什么这个方法可行?

CountDownLatch会让等待的线程进入休眠状态(不占用CPU),直到countDown()被调用(任务完成或失败时),线程才会被唤醒继续执行。用AtomicReference是因为在回调方法里给外部变量赋值需要保证线程安全,避免并发问题。

最后再提醒一句:如果是在UI线程(比如Android主线程、Swing的EDT),绝对不要用方案2,否则会导致界面冻结,用户体验极差,甚至触发ANR(应用无响应)。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.28 06:35:22