前言
在Java 8中,引入了CompletableFuture类,它是Future的增强版,提供了更加灵活的异步编程方式,能够更好地利用多线程的优势。本文将详细讲解CompletableFuture的使用方法,并结合多线程实现异步编程。
CompletableFuture的概念
CompletableFuture是Java 8中新增的一个类,它实现了Future和CompletionStage接口,提供了一种更加灵活的异步编程方式。CompletableFuture可以看作是一个包含了计算结果的容器,可以在计算完成后获取结果,也可以在计算完成前执行一些操作。
与Future相比,CompletableFuture提供了更多的方法来处理异步计算的结果。它支持链式调用、组合多个CompletableFuture、异常处理等操作。
CompletableFuture的创建
CompletableFuture可以通过以下方式创建:
1. CompletableFuture.supplyAsync()
CompletableFuture.supplyAsync()方法可以创建一个异步计算任务,返回一个CompletableFuture对象。它接收一个Supplier类型的参数,用于执行异步计算。
示例代码:
CompletableFuture<Integer> future = CompletableFuture.supplyAsync(() -> {
// 异步计算任务
return 1 + 2;
});
又如:
import java.util.concurrent.*;
public class AsyncService {
private final ExecutorService executorService;
public AsyncService(int poolSize) {
this.executorService = Executors.newFixedThreadPool(poolSize);
}
// 异步方法1
public CompletableFuture<String> asyncMethod1() {
return CompletableFuture.supplyAsync(() -> {
// 执行一些长时间运行的任务...
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
return "Result of Method1";
}, executorService);
}
// 异步方法2
public CompletableFuture<String> asyncMethod2() {
return CompletableFuture.supplyAsync(() -> {
// 执行一些长时间运行的任务...
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
return "Result of Method2";
}, executorService);
}
// 关闭线程池
public void shutdown() {
executorService.shutdown();
}
public static void main(String[] args) throws ExecutionException, InterruptedException {
AsyncService asyncService = new AsyncService(10);
CompletableFuture<String> future1 = asyncService.asyncMethod1();
CompletableFuture<String> future2 = asyncService.asyncMethod2();
System.out.println(future1.get());
System.out.println(future2.get());
asyncService.shutdown();
}
}
2. CompletableFuture.runAsync()
CompletableFuture.runAsync()方法也可以创建一个异步计算任务,返回一个CompletableFuture对象。它接收一个Runnable类型的参数,用于执行异步计算。
示例代码:
CompletableFuture<Void> future = CompletableFuture.runAsync(() -> {
// 异步计算任务
System.out.println("异步计算任务执行完成");
});
CompletableFuture.runAsync()
方法用于执行没有返回值的异步任务,又如:
import java.util.concurrent.*;
public class AsyncService {
private final ExecutorService executorService;
public AsyncService(int poolSize) {
this.executorService = Executors.newFixedThreadPool(poolSize);
}
// 异步方法1
public CompletableFuture<Void> asyncMethod1() {
return CompletableFuture.runAsync(() -> {
// 执行一些长时间运行的任务...
try {
System.out.println("Starting Method1...");
Thread.sleep(2000);
System.out.println("Finished Method1");
} catch (InterruptedException e) {
e.printStackTrace();
}
}, executorService);
}
// 异步方法2
public CompletableFuture<Void> asyncMethod2() {
return CompletableFuture.runAsync(() -> {
// 执行一些长时间运行的任务...
try {
System.out.println("Starting Method2...");
Thread.sleep(2000);
System.out.println("Finished Method2");
} catch (InterruptedException e) {
e.printStackTrace();
}
}, executorService);
}
// 关闭线程池
public void shutdown() {
executorService.shutdown();
}
public static void main(String[] args) throws ExecutionException, InterruptedException {
AsyncService asyncService = new AsyncService(10);
CompletableFuture<Void> future1 = asyncService.asyncMethod1();
CompletableFuture<Void> future2 = asyncService.asyncMethod2();
CompletableFuture.allOf(future1, future2).join(); // 等待所有异步任务完成
asyncService.shutdown();
}
}
3. CompletableFuture.completedFuture()
CompletableFuture.completedFuture()方法可以创建一个已经完成的CompletableFuture对象,返回一个CompletableFuture对象。它接收一个静态值作为参数,表示已经完成的计算结果。
示例代码:
CompletableFuture<String> future = CompletableFuture.completedFuture("已经完成的计算结果");
CompletableFuture的使用
1. 获取计算结果
CompletableFuture的get()方法可以用于获取计算结果,如果计算尚未完成,则会阻塞当前线程直到计算完成。
示例代码:
CompletableFuture<Integer> future = CompletableFuture.supplyAsync(() -> {
// 异步计算任务
return 1 + 2;
});
int result = future.get();
System.out.println(result);
2. 异步回调
CompletableFuture的thenApply()方法可以用于异步回调,它接收一个Function类型的参数,用于对计算结果进行转换。thenApply()方法返回一个新的CompletableFuture对象,它的计算结果为转换后的结果。
示例代码:
CompletableFuture<Integer> future = CompletableFuture.supplyAsync(() -> {
// 异步计算任务
return 1 + 2;
});
CompletableFuture<String> future2 = future.thenApply(result -> "计算结果为:" + result);
String result2 = future2.get();
System.out.println(result2);
3. 异步消费
CompletableFuture的thenAccept()方法可以用于异步消费,它接收一个Consumer类型的参数,用于对计算结果进行消费。thenAccept()方法返回一个新的CompletableFuture对象,它的计算结果为原始结果。
示例代码:
CompletableFuture<Integer> future = CompletableFuture.supplyAsync(() -> {
// 异步计算任务
return 1 + 2;
});
CompletableFuture<Void> future2 = future.thenAccept(result -> {
System.out.println("计算结果为:" + result);
});
future2.get();
4. 异步组合
CompletableFuture的thenCompose()方法可以用于异步组合,它接收一个Function类型的参数,用于对计算结果进行组合。thenCompose()方法返回一个新的CompletableFuture对象,它的计算结果为组合后的结果。
示例代码:
CompletableFuture<Integer> future = CompletableFuture.supplyAsync(() -> {
// 异步计算任务
return 1 + 2;
});
CompletableFuture<Integer> future2 = future.thenCompose(result -> CompletableFuture.supplyAsync(() -> {
// 异步计算任务
return result * 2;
}));
int result2 = future2.get();
System.out.println(result2);
5. 异步组合多个CompletableFuture
CompletableFuture的thenCombine()方法可以用于异步组合多个CompletableFuture,它接收一个BiFunction类型的参数,用于对多个计算结果进行组合。thenCombine()方法返回一个新的CompletableFuture对象,它的计算结果为组合后的结果。
示例代码:
CompletableFuture<Integer> future1 = CompletableFuture.supplyAsync(() -> {
// 异步计算任务
return 1 + 2;
});
CompletableFuture<Integer> future2 = CompletableFuture.supplyAsync(() -> {
// 异步计算任务
return 3 + 4;
});
CompletableFuture<Integer> future3 = future1.thenCombine(future2, (result1, result2) -> {
// 异步计算任务
return result1 + result2;
});
int result3 = future3.get();
System.out.println(result3);
6. 异常处理
CompletableFuture的exceptionally()方法可以用于异常处理,它接收一个Function类型的参数,用于处理异常情况。exceptionally()方法返回一个新的CompletableFuture对象,它的计算结果为原始结果或异常处理结果。
示例代码:
CompletableFuture<Integer> future = CompletableFuture.supplyAsync(() -> {
// 异步计算任务
throw new RuntimeException("计算异常");
});
CompletableFuture<Integer> future2 = future.exceptionally(e -> {
System.out.println("计算出现异常:" + e.getMessage());
return 0;
});
int result2 = future2.get();
System.out.println(result2);
多线程结合使用
CompletableFuture可以与多线程结合使用,实现更加高效的异步编程。下面是一个简单的示例,演示了如何使用CompletableFuture和多线程实现异步计算。
public class CompletableFutureDemo {
public static void main(String[] args) throws Exception {
ExecutorService executorService = Executors.newFixedThreadPool(3);
CompletableFuture<Integer> future1 = CompletableFuture.supplyAsync(() -> {
// 异步计算任务
return 1 + 2;
}, executorService);
CompletableFuture<Integer> future2 = CompletableFuture.supplyAsync(() -> {
// 异步计算任务
return 3 + 4;
}, executorService);
CompletableFuture<Integer> future3 = future1.thenCombineAsync(future2, (result1, result2) -> {
// 异步计算任务
return result1 + result2;
}, executorService);
int result = future3.get();
System.out.println(result);
executorService.shutdown();
}
}
在上面的示例中,我们使用了ExecutorService来创建线程池,并将其传递给CompletableFuture的方法中。这样可以控制异步计算的线程池大小,避免创建太多线程导致性能下降。
总结
CompletableFuture是Java 8中新增的一个类,它实现了Future和CompletionStage接口,提供了一种更加灵活的异步编程方式。CompletableFuture可以看作是一个包含了计算结果的容器,可以在计算完成后获取结果,也可以在计算完成前执行一些操作。
CompletableFuture提供了更多的方法来处理异步计算的结果,包括获取计算结果、异步回调、异步消费、异步组合、异常处理等操作。它可以与多线程结合使用,实现更加高效的异步编程。
在使用CompletableFuture时,需要注意线程池的大小,避免创建过多线程导致性能下降。除此之外,我们还可以使用CompletableFuture来处理大量的异步任务,提高系统的并发能力和性能。
👉 💐🌸 公众号请关注 "果酱桑", 一起学习,一起进步! 🌸💐