如何正确使用Java Future对象的isDone()方法获取有效结果
Future.isDone() 正确使用指南
基础特性说明
isDone() 是非阻塞方法,只要任务进入终止状态就会返回true,终止状态包含:正常执行完成、执行过程抛出异常、任务被主动取消三种场景,不会等待任务执行完成,调用后会立刻返回当前状态。
正确使用方式
1. 带间隔/穿插其他逻辑的轮询
不要提交任务后立刻死循环空转调用isDone(),会无意义占用CPU资源,需要在两次检查之间加入休眠时间,或者穿插执行不依赖当前任务结果的其他业务逻辑:
Future<?> future = dbChangeService.submit(dbChgProcessor); // 轮询检查逻辑 while (!future.isDone()) { // 按业务可接受的延迟设置检查间隔,示例为100ms Thread.sleep(100); // 此处可执行其他不依赖该任务结果的业务逻辑 doOtherUnrelatedWork(); } // 确认任务结束后调用get(),此时不会阻塞,可以安全处理结果/异常 try { future.get(); // 任务正常执行完成的后续逻辑 handleTaskSuccess(); } catch (ExecutionException e) { // 处理任务执行过程抛出的业务异常 handleTaskError(e.getCause()); } catch (CancellationException e) { // 处理任务被取消的场景 handleTaskCancelled(); } catch (InterruptedException e) { Thread.currentThread().interrupt(); throw new RuntimeException("当前线程被中断", e); }
2. 嵌入现有定时调度逻辑
如果你的项目本身有通用定时调度器,可以将isDone()检查作为定时任务注册,不需要单独开线程做轮询,适合对任务完成延迟敏感度不高的场景。
注意事项
isDone()返回true不代表任务执行成功,异常终止、被取消的任务也会触发isDone()返回true,必须调用get()捕获对应异常才能判断任务最终执行状态。- 避免无间隔连续调用
isDone(),极端场景下空转轮询的CPU占用会达到100%,性能远低于直接调用阻塞的get()方法。
更优方案(Java 8+)
如果你的项目使用Java 8及以上版本,推荐直接用CompletableFuture替代原生Future,自带异步回调能力,不需要手动写轮询逻辑:
// 提交任务到自定义线程池 CompletableFuture.runAsync(dbChgProcessor, dbChangeService) // 任务正常完成后的回调,自动异步触发 .thenRun(() -> handleTaskSuccess()) // 任务执行异常时的回调,自动异步触发 .exceptionally(e -> { handleTaskError(e); return null; });
内容的提问来源于stack exchange,提问作者Thomas Lee Sebastian
相关产品推荐
相关产品推荐

