1.引言
Java 9引入了两个新的方法orTimeout()和completeOnTimeout(),这些方法是在CompletionStage及其子类中定义的,这为Java异步编程框架提供了更多的灵活性。两个方法都用于处理Future异步计算的超时,但它们之间有一些区别。
2.什么是Future和CompletionStage?
在介绍方法的区别之前,我们需要了解一下Future和CompletionStage是什么。
Future是一个接口,表示一个尚未完成但可能在未来完成的计算。通过Future,我们可以通过
poll()或get()方法来检查其是否完成,如果完成了,我们可以访问结果或异常。
CompletionStage是一个接口,表示异步操作的阶段,可能会生成阶段之间的转换。在CompletionStage
中,我们可以定义处理已完成任务的方法,此任务可能是
- 异步计算
- 操作执行
- 执行IO操作
3.orTimeout()方法
orTimeout()方法使我们能够可靠地执行异步操作的超时管理。此方法等待stage操作完成的时间间隔,如果等待时间超过此阈值或完成时间,则抛出TimeoutException。
此方法返回一个新的CompletionStage对象,返回的对象与原始对象相同,但是当原始对象的操作超出规定的时间限制时,返回的CompletionStage将产生一个TimeoutException异常,例如:
CompletableFuture future = CompletableFuture.supplyAsync(() -> {
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
return 1;
});
CompletionStage timedOut = future.orTimeout(1, TimeUnit.SECONDS);
timedOut.whenComplete((result, error) -> {
if (error != null) {
System.out.println(error);
} else {
System.out.println(result);
}
});
上述代码中,我们使用CompletableFuture创建一个异步任务,并设置执行时间为2秒,我们使用orTimeout()方法,以此告诉CompletableFuture,如果任务执行时间超过1秒钟,则超时。当超时的时候,我们将会得到一个TimeoutException异常。
注意:orTimeout()方法的超时时间需小于异步任务的执行时间。
4.completeOnTimeout()方法
completeOnTimeout()方法也能够可靠地执行异步操作的超时管理,但与orTimeout()方法不同的是,当任务超时时,它不会抛出异常,而是使用给定的默认值来完成该任务。
此方法返回一个新的CompletionStage对象,返回的对象与原始对象相同,但当原始对象的操作超出规定的时间限制时,返回的CompletionStage将产生在预定时间之前生成的结果或默认值,例如:
CompletableFuture future = CompletableFuture.supplyAsync(() -> {
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
return 1;
});
CompletionStage timedOut = future.completeOnTimeout(2, 1, TimeUnit.SECONDS);
timedOut.whenComplete((result, error) -> {
if (error != null) {
System.out.println(error);
} else {
System.out.println(result);
}
});
上述代码中,我们使用CompletableFuture创建一个异步任务,并设置执行时间为2秒。我们使用completeOnTimeout()方法,以此告诉CompletableFuture,如果任务执行时间超过1秒钟,则使用我们提供的默认值2来完成任务。当超时的时候,我们将会得到值为2的result。
5.orTimeout()方法和completeOnTimeout()方法的区别
orTimeout()方法和completeOnTimeout()方法都是处理异步操作超时的工具,但它们之间存在以下几个区别:
5.1 接收参数的类型不同。
orTimeout()方法使用TimeUnit作为计时单位,而completeOnTimeout()方法使用异步任务类型的默认值作为参数。
5.2 处理超时的方式不同。
当异步操作超出规定时间间隔时,orTimeout()方法将会抛出TimeoutException异常,而completeOnTimeout()方法则会使用默认值完成该任务。
5.3 延迟时间不同。
orTimeout()方法的执行时间不能超过指定的延迟时间,否则将抛出TimeoutException异常,而completeOnTimeout()方法可以延长一段时间,并使用默认值完成异步操作。
6.结束语
在Java 9中,orTimeout()方法和completeOnTimeout()方法为我们提供了更多的选项,以管理我们的异步操作超时。虽然两种方法似乎很相似,但对于应用程序的不同需求,选择合适的方法将会更加有效和灵活。