CompletableFuture获取执行结果的方法

join()

CompletableFuture.join() 是用于等待异步任务完成并获取结果的方法。

        在使用 CompletableFuture.join() 方法时,如果异步任务已经完成,则该方法会立即返回任务的执行结果;如果异步任务尚未完成,则该方法会阻塞当前线程,直到任务执行完成并返回结果为止。

下面是 CompletableFuture.join() 方法的具体介绍:

方法声明:public T join()

方法说明:等待此 CompletableFuture 的完成并返回结果。

方法返回:此 CompletableFuture 的结果。

方法抛出的异常:CompletionException(如果此 CompletableFuture 计算过程中出现了异常)。

        举个例子,假设我们有一个异步任务,需要访问某个远程服务并返回一个字符串结果。我们可以使用 CompletableFuture 来实现这个异步任务,并通过 CompletableFuture.join() 方法来等待任务执行完成并获取结果,示例如下所示:

CompletableFuture future = CompletableFuture.supplyAsync(() -> {
    // 访问远程服务并返回结果
});

// 等待异步任务完成并获取结果
String result = future.join();

        在上面的示例中,我们首先创建了一个 CompletableFuture 对象,使用 supplyAsync() 方法来指定一个异步任务,该异步任务访问远程服务并返回结果。接着,我们使用 CompletableFuture.join() 方法来等待任务执行完成并获取结果。当任务执行完成后,join() 方法会立即返回任务的执行结果,从而使我们能够及时获取任务的执行结果。

        总之,CompletableFuture.join() 是 CompletableFuture 类中的一个重要方法,它可以用于等待异步任务完成并获取结果。如果我们需要在 CompletableFuture 中获取异步任务的执行结果,就可以使用 join() 方法来完成这个操作。需要注意的是,在使用 join() 方法时,我们需要注意防止出现线程死锁或者无限阻塞的情况,以保证程序的正常执行。

防止出现线程死锁或者无限阻塞的方法

不要在同一线程中嵌套使用 join() 方法

        如果在一个线程中嵌套调用了 join() 方法,那么有可能会出现线程死锁的问题,因为 join() 方法会阻塞当前线程,并等待异步任务完成。为了避免这种情况,我们应该避免在同一线程中嵌套调用 join() 方法,而是应该将异步任务提交到线程池中执行。

使用 CompletableFuture.getNow() 方法获取结果

        如果想要获取 CompletableFuture 的执行结果,但又不想阻塞当前线程,可以使用 CompletableFuture.getNow() 方法来获取结果。该方法会立即返回 CompletableFuture 的结果,如果结果还没有计算完成,则返回默认值。

设置超时时间

        如果异步任务不能在规定时间内完成,那么 join() 方法会一直阻塞当前线程,这可能会导致程序陷入无限等待的状态。因此,在使用 join() 方法时,可以使用 CompletableFuture.orTimeout() 和 CompletableFuture.get(timeout, unit) 方法设置超时时间,如果超过规定时间还没有得到结果,则抛出异常。

        CompletableFuture.orTimeout() 方法是在 Java 9 中引入的,它可以设置 CompletableFuture 的最大等待时间,如果 CompletableFuture 在指定的时间内没有完成计算,则抛出 TimeoutException 异常,示例如下:

CompletableFuture future = CompletableFuture.supplyAsync(() -> {
    // 访问远程服务并返回结果
});

// 设置最大等待时间为1秒
String result = future.orTimeout(1, TimeUnit.SECONDS).join();

        在上面的示例中,我们首先创建了一个 CompletableFuture 对象,并使用 supplyAsync() 方法指定一个异步任务。接着,我们通过调用 orTimeout() 方法来设置 CompletableFuture 的最大等待时间为1秒,并使用 join() 方法来等待异步任务执行完成并获取结果。如果在1秒内任务没有完成,orTimeout() 方法就会抛出 TimeoutException 异常,从而保证程序能够及时结束等待操作。 

使用 CompletableFuture.completeExceptionally() 方法处理异常

        在使用 CompletableFuture 时,异步任务可能会遇到各种异常情况,例如网络异常、超时等。如果不处理这些异常,可能会导致程序出错或者陷入无限等待的状态。为了避免这种情况,我们可以使用 CompletableFuture.completeExceptionally() 方法来处理异常,并及时通知调用方。

        综上所述,使用 CompletableFuture.join() 方法时,需要注意防止出现线程死锁或者无限阻塞的情况。我们可以采用上述措施来避免这种情况的发生,以保证程序的正常执行。

CompletableFuture.get()

        CompletableFuture.get() 方法是一个阻塞方法,它会一直阻塞当前线程,直到 CompletableFuture 完成计算并返回结果。如果 CompletableFuture 计算过程中遇到异常,get() 方法会抛出 ExecutionException 异常,并将原始异常作为它的 cause。

CompletableFuture.get() 方法有两种重载形式:

get()

该方法会一直阻塞当前线程直到 CompletableFuture 完成计算并返回结果,示例如下:

CompletableFuture future = CompletableFuture.supplyAsync(() -> {
    // 访问远程服务并返回结果
});

// 阻塞当前线程,直到 CompletableFuture 返回结果
String result = future.get();

        在上面的示例中,我们首先创建了一个 CompletableFuture 对象,并使用 supplyAsync() 方法指定一个异步任务。接着,我们通过调用 get() 方法来阻塞当前线程,并等待 CompletableFuture 完成计算并返回结果。

get(timeout, unit)

        该方法允许我们设置最大等待时间,如果在指定的等待时间内 CompletableFuture 没有完成计算,则抛出 TimeoutException 异常。示例如下:

CompletableFuture future = CompletableFuture.supplyAsync(() -> {
    // 访问远程服务并返回结果
});

try {
    // 最大等待时间为1秒
    String result = future.get(1, TimeUnit.SECONDS);
} catch (TimeoutException e) {
    // 处理超时异常
} catch (InterruptedException | ExecutionException e) {
    // 处理其他异常
}

        在上面的示例中,我们首先创建了一个 CompletableFuture 对象,并使用 supplyAsync() 方法指定一个异步任务。接着,我们通过调用 get(timeout, unit) 方法来设置最大等待时间为1秒,并阻塞当前线程,直到 CompletableFuture 完成计算并返回结果,或者等待时间超时。

        需要注意的是,get(timeout, unit) 方法会一直阻塞当前线程,直到 CompletableFuture 计算完成或者等待时间超时。因此,在使用该方法时应该尽量避免在主线程中调用它,而是应该将 CompletableFuture 提交到线程池中执行,以充分发挥异步操作的优势。

getNow(T value)

        CompletableFuture.getNow(T value) 方法是一个非阻塞方法,它会在 CompletableFuture 完成计算之前返回一个默认值,如果 CompletableFuture 已经完成计算,则返回计算结果。该方法有一个参数,表示默认值。

示例如下:

CompletableFuture future = CompletableFuture.supplyAsync(() -> {
    // 访问远程服务并返回结果
});

// 在 CompletableFuture 完成计算之前返回默认值,如果 CompletableFuture 已经完成计算,则返回计算结果
String result = future.getNow("default value");

        在上面的示例中,我们首先创建了一个 CompletableFuture 对象,并使用 supplyAsync() 方法指定一个异步任务。接着,我们通过调用 getNow() 方法来获取 CompletableFuture 的计算结果,或者在 CompletableFuture 完成计算之前返回默认值。如果 CompletableFuture 已经完成计算,则返回计算结果;如果 CompletableFuture 还没有完成计算,则返回默认值。

        需要注意的是,getNow() 方法是一个非阻塞方法,可以立即返回结果但不保证结果的正确性。因此,在使用该方法时应该加上适当的逻辑处理,以确保程序的正确性。

isDone()

        CompletableFuture.isDone() 方法是用于判断 CompletableFuture 是否已经完成计算的方法。如果 CompletableFuture 已经完成计算,则返回 true;否则返回 false。

示例如下:

CompletableFuture future = CompletableFuture.supplyAsync(() -> {
    // 访问远程服务并返回结果
});

// 判断 CompletableFuture 是否已经完成计算
boolean done = future.isDone();

        在上面的示例中,我们首先创建了一个 CompletableFuture 对象,并使用 supplyAsync() 方法指定一个异步任务。接着,我们通过调用 isDone() 方法来判断 CompletableFuture 是否已经完成计算并获取计算结果。如果 CompletableFuture 已经完成计算,则返回 true;否则返回 false。

        需要注意的是,isDone() 方法只能用于检查 CompletableFuture 是否已经完成计算,不能用于等待 CompletableFuture 完成计算。如需等待 CompletableFuture 完成计算并获取计算结果,可以使用 CompletableFuture.join() 或 CompletableFuture.get() 方法。

complete(T value) 

        CompletableFuture.complete(T value) 方法是用于手动完成 CompletableFuture 计算的方法。该方法有一个参数,表示计算的结果值。

示例如下:

CompletableFuture future = new CompletableFuture<>();

// 手动完成 CompletableFuture 计算并设置计算结果
future.complete("result");

// 获取 CompletableFuture 的计算结果
String result = future.join();

        在上面的示例中,我们首先创建了一个 CompletableFuture 对象,并使用构造方法创建一个未完成的 CompletableFuture。接着,我们通过调用 complete() 方法来手动完成 CompletableFuture 的计算并设置计算结果。

        需要注意的是,如果 CompletableFuture 已经完成计算,则再次调用 complete() 方法会抛出异常。因此,在调用 complete() 方法之前应该使用 isDone() 方法判断 CompletableFuture 是否已经完成计算。

你可能感兴趣的:(并发编程,java,java)