CompletableFuture.supplyAsync 超时设置
时间: 2025-01-23 12:11:02 浏览: 18
使用 CompletableFuture
实现异步任务超时
对于 CompletableFuture.supplyAsync()
创建的任务,可以利用多种方式来设置超时机制。以下是几种常见的实现方法:
方法一:使用 orTimeout
自 Java 9 起引入了 orTimeout(long timeout, TimeUnit unit)
方法,该方法允许指定一个最大等待时间,一旦超出这个时间段而任务仍未完成,则会抛出 CompletionException
异常[^3]。
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.TimeUnit;
public class TimeoutExample {
public static void main(String[] args) throws Exception {
CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> {
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
return "Operation Result";
}).orTimeout(1, TimeUnit.SECONDS);
try {
System.out.println(future.get());
} catch (Exception e) {
System.err.println("Task timed out or encountered an error.");
}
}
}
此代码片段展示了当任务执行超过一秒时将会被取消并抛出异常的情况。
方法二:结合 completeOnTimeout
同样适用于 Java 9 及以上版本的是 completeOnTimeout(T value, long timeout, TimeUnit unit)
方法。不同于 orTimeout
的强制终止行为,这里是在规定时间内未能得到结果的情况下返回默认值而不是抛出异常。
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.TimeUnit;
public class CompleteOnTimeoutExample {
public static void main(String[] args) throws Exception {
String defaultValue = "Default Value";
CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> {
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
return "Actual Operation Result";
}).completeOnTimeout(defaultValue, 1, TimeUnit.SECONDS);
System.out.println(future.join()); // 输出可能是 "Default Value"
}
}
这段程序会在两秒钟内无法获得实际运算结果时自动填充预设的字符串作为替代输出。
方法三:通过外部定时器配合 cancel
针对低于 Java 9 版本环境下的解决方案,可以通过创建另一个线程或调度服务,在经过一定延迟后尝试调用 future.cancel(true)
来中断长时间运行的任务。不过需要注意这种方式并不能保证一定能成功停止目标线程的工作,因为这取决于具体业务逻辑是否响应中断信号[^4]。
import java.util.concurrent.*;
class CancelAfterDelayExample {
private static final ExecutorService executor = Executors.newCachedThreadPool();
public static void main(String[] args) throws InterruptedException {
Runnable task = () -> {
while (!Thread.currentThread().isInterrupted()) {
try {
Thread.sleep(Long.MAX_VALUE); // Simulate a very long operation.
} catch (InterruptedException ignored) {}
}
};
Future<?> future = executor.submit(task);
ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1);
scheduler.schedule(() -> future.cancel(true), 1, TimeUnit.SECONDS);
Thread.sleep(2 * 1000L); // Wait to see the effect of cancellation.
System.exit(0);
}
}
在这个例子中,即使主线程已经结束,后台工作仍然会被安排在一个短暂的时间间隔之后被请求取消。
阅读全文
相关推荐


















