Java中的CompletableFuture使用文档

1. 引言

在现代软件开发中,异步编程已经成为处理高并发和响应式系统的关键技术之一。Java 8引入了CompletableFuture,这是一种功能强大且灵活的异步编程API,它扩展了Future接口,提供了许多新的特性,使得编写非阻塞式的异步代码更加容易。本文档旨在介绍CompletableFuture的基础知识及其高级用法,帮助开发者更好地理解和应用这一工具。

2. CompletableFuture简介

CompletableFuturejava.util.concurrent包下的一个类,它代表了一个可能会在将来完成的计算的结果。它可以用来异步地执行任务,并且提供了一种优雅的方式来处理这些任务的结果、异常和组合多个任务。

3. 创建CompletableFuture

3.1 使用静态工厂方法

CompletableFuture提供了几个静态工厂方法来创建不同的CompletableFuture实例:

  • supplyAsync(Supplier<T> supplier):创建一个异步完成的CompletableFuture,使用默认的ForkJoinPool.commonPool()来执行supplier
  • runAsync(Runnable runnable):创建一个异步执行的CompletableFuture,不返回任何结果。
  • completedFuture(V value):创建一个已完成的CompletableFuture,立即返回给定的结果值。

示例:

1
2
3
4
5
6
7
8
import java.util.concurrent.CompletableFuture;

public class CompletableFutureExample {
public static void main(String[] args) {
CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> "Hello CompletableFuture!");
CompletableFuture<Void> runFuture = CompletableFuture.runAsync(() -> System.out.println("Running async task"));
}
}
3.2 使用构造器

你也可以通过CompletableFuture的构造器来创建实例,并且手动完成它。

示例:

1
2
3
4
5
6
7
8
9
import java.util.concurrent.CompletableFuture;

public class CompletableFutureExample {
public static void main(String[] args) {
CompletableFuture<String> future = new CompletableFuture<>();
// 执行一些操作...
future.complete("Hello CompletableFuture!");
}
}

4. 处理CompletableFuture的结果

4.1 thenApply

thenApply方法可以用于在前一个阶段完成后执行另一个任务,并且该任务可以访问前一阶段的结果。

示例:

1
2
3
4
5
6
7
8
import java.util.concurrent.CompletableFuture;

public class CompletableFutureExample {
public static void main(String[] args) {
CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> "Hello CompletableFuture!")
.thenApply(result -> result.toUpperCase()); // 将结果转换为大写
}
}
4.2 thenAccept

thenAccept方法用于在前一个阶段完成后执行一个消费型操作,它不会返回任何结果。

示例:

1
2
3
4
5
6
7
8
import java.util.concurrent.CompletableFuture;

public class CompletableFutureExample {
public static void main(String[] args) {
CompletableFuture.supplyAsync(() -> "Hello CompletableFuture!")
.thenAccept(result -> System.out.println("Received result: " + result));
}
}
4.3 thenRun

thenRun方法用于在前一个阶段完成后执行一个Runnable任务,它不依赖于前一阶段的结果。

示例:

1
2
3
4
5
6
7
8
import java.util.concurrent.CompletableFuture;

public class CompletableFutureExample {
public static void main(String[] args) {
CompletableFuture.supplyAsync(() -> "Hello CompletableFuture!")
.thenRun(() -> System.out.println("Task completed"));
}
}

5. 处理异常

5.1 exceptionally

exceptionally方法用于处理前一阶段抛出的异常。

示例:

1
2
3
4
5
6
7
8
9
10
11
12
import java.util.concurrent.CompletableFuture;

public class CompletableFutureExample {
public static void main(String[] args) {
CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> {
throw new RuntimeException("Oops, something went wrong!");
}).exceptionally(ex -> {
System.err.println("Caught exception: " + ex.getMessage());
return "Error occurred"; // 返回一个默认值
});
}
}
5.2 handle

handle方法类似于thenApply,但它可以处理正常结果和异常两种情况。

示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
import java.util.concurrent.CompletableFuture;

public class CompletableFutureExample {
public static void main(String[] args) {
CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> {
throw new RuntimeException("Oops, something went wrong!");
}).handle((result, ex) -> {
if (ex == null) {
return result;
} else {
System.err.println("Caught exception: " + ex.getMessage());
return "Error occurred"; // 返回一个默认值
}
});
}
}

6. 组合多个CompletableFuture

6.1 allOf

allOf方法用于等待一组CompletableFuture全部完成。

示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
import java.util.concurrent.CompletableFuture;

public class CompletableFutureExample {
public static void main(String[] args) throws Exception {
CompletableFuture<String> future1 = CompletableFuture.supplyAsync(() -> "Result 1");
CompletableFuture<String> future2 = CompletableFuture.supplyAsync(() -> "Result 2");

CompletableFuture<Void> combinedFuture = CompletableFuture.allOf(future1, future2);
combinedFuture.get(); // 等待所有任务完成

System.out.println(future1.get());
System.out.println(future2.get());
}
}
6.2 anyOf

anyOf方法用于等待一组CompletableFuture中的任何一个完成。

示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
import java.util.concurrent.CompletableFuture;

public class CompletableFutureExample {
public static void main(String[] args) throws Exception {
CompletableFuture<String> future1 = CompletableFuture.supplyAsync(() -> {
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
throw new RuntimeException(e);
}
return "Result 1";
});

CompletableFuture<String> future2 = CompletableFuture.supplyAsync(() -> "Result 2");

CompletableFuture<Object> combinedFuture = CompletableFuture.anyOf(future1, future2);
Object result = combinedFuture.get(); // 等待任一任务完成

System.out.println("First completed result: " + result);
}
}

7. 同步与异步

尽管CompletableFuture的主要用途是处理异步任务,但它也提供了同步的方法来获取结果,如get()方法。然而,get()方法会阻塞当前线程直到结果可用,因此在多线程环境中应谨慎使用。

8. 使用自定义执行器

你可以通过传递一个Executor参数给supplyAsyncrunAsync方法来指定一个自定义的线程池。

示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class CompletableFutureExample {
public static void main(String[] args) {
ExecutorService executor = Executors.newFixedThreadPool(5);

CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> "Hello CompletableFuture!", executor);

// 关闭线程池
executor.shutdown();
}
}

9. 总结

通过上述示例,你应该对CompletableFuture有了初步的了解,并且知道如何使用它来进行异步编程。CompletableFuture不仅简化了异步编程模型,还提供了强大的组合功能,使得异步编程变得更加简洁和高效。希望这份文档能帮助你在实际项目中更好地利用这一工具。