目录
前言:
异步编程相关实现方式:
Java8 Stream简单实现:
并行操作:
详细代码:
输出结果:
异步操作:
详细代码:
结果输出:
Java CompletableFuture异步操作的示例:
CompletableFuture 和 CompletableFuture.delayedExecutor 方法
输出结果:
前言:
🔣 主要是记录个笔记,对你有帮助的话,那就更好啦
异步编程相关实现方式:
- 回调函数(Callback):通过在方法调用中传递回调函数,可以在异步操作完成后执行回调方法。
- Future和CompletableFuture:Future用于异步操作的结果获取,CompletableFuture则提供了更多的方法,例如thenApply、thenCombine等,可以方便地进行异步操作的组合和串联。
- RxJava:提供了丰富的异步编程方法,例如Observable、Subject、Scheduler等,支持异步操作的组合和流式处理。
- Java 8 Stream API:提供了类似于函数式编程的操作方式,可以方便地进行并行处理和异步操作的组合。
- Java 9 Flow API:提供了Reactive Streams的实现,支持异步消息传递和背压控制。
- CompletableFuture和Stream API的结合:Java 9引入的新特性,可以将Stream API和CompletableFuture结合起来使用,实现更加方便的异步编程。
Java8 Stream简单实现:
并行操作:
List<String> list = Arrays.asList("apple", "banana", "cherry", "date", "elderberry", "fig");
// 串行处理
list.stream()
.map(String::toUpperCase)
.forEach(System.out::println);
// 并行处理
list.parallelStream()
.map(String::toUpperCase)
.forEach(System.out::println);
- 上面的代码使用了parallelStream()方法,将串行处理的Stream转换为并行处理的Stream,提高了处理的效率。
详细代码:
import java.util.Arrays;
public class StreamParallelDemo {
public static void main(String[] args) {
int[] nums = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
// 串行流
Arrays.stream(nums)
.map(StreamParallelDemo::process)
.forEach(System.out::println);
// 并行流
Arrays.stream(nums)
.parallel()
.map(StreamParallelDemo::process)
.forEach(System.out::println);
}
public static int process(int num) {
System.out.println("Processing " + num + " in thread " + Thread.currentThread().getName());
return num * 2;
}
}
- 我们首先定义了一个整数数组 nums,然后使用 Java 8 Stream 的 map 方法对数组中的每个元素进行处理,并使用 forEach 方法输出处理结果。我们分别使用串行流和并行流来处理数组中的元素,其中并行流使用 parallel 方法来启用并行操作。
- 在 process 方法中,我们打印了当前处理的元素和线程名称,以便观察并行操作的效果。运行该示例,可以看到如下输出:
输出结果:
Processing 1 in thread main
2
Processing 2 in thread main
4
Processing 3 in thread main
6
Processing 4 in thread main
8
Processing 5 in thread main
10
Processing 6 in thread main
12
Processing 7 in thread main
14
Processing 8 in thread main
16
Processing 9 in thread main
18
Processing 10 in thread main
20
Processing 1 in thread ForkJoinPool.commonPool-worker-1
Processing 2 in thread ForkJoinPool.commonPool-worker-2
Processing 3 in thread ForkJoinPool.commonPool-worker-3
Processing 4 in thread ForkJoinPool.commonPool-worker-4
Processing 5 in thread ForkJoinPool.commonPool-worker-5
Processing 6 in thread ForkJoinPool.commonPool-worker-6
Processing 7 in thread ForkJoinPool.commonPool-worker-7
Processing 8 in thread ForkJoinPool.commonPool-worker-8
Processing 9 in thread ForkJoinPool.commonPool-worker-1
Processing 10 in thread ForkJoinPool.commonPool-worker-2
2
4
6
8
10
12
14
16
18
20
- 可以看到,在串行流中,所有元素都是在主线程中处理的,而在并行流中,元素被分配到了不同的线程中进行处理,从而提高了处理效率。需要注意的是,并行流的效率提高并不是绝对的,它还受到数据规模、处理逻辑等因素的影响。因此,在使用并行流时,需要根据具体情况进行测试和优化。
异步操作:
CompletableFuture<Integer> future = CompletableFuture.supplyAsync(() -> {
// 异步操作,返回一个结果
return 42;
});
// 处理异步操作的结果
future.thenAccept(System.out::println);
- 上面的代码使用了CompletableFuture.supplyAsync()方法,实现了一个异步操作,然后使用thenAccept()方法处理异步操作的结果。也可以使用thenApply()方法对异步操作的结果进行转换,或者使用thenCompose()方法串联异步操作。
详细代码:
import java.util.Arrays;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
public class StreamAsyncDemo {
public static void main(String[] args) throws ExecutionException, InterruptedException {
int[] nums = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
CompletableFuture<Integer>[] futures = Arrays.stream(nums)
.mapToObj(StreamAsyncDemo::processAsync)
.toArray(CompletableFuture[]::new);
CompletableFuture.allOf(futures).join();
for (CompletableFuture<Integer> future : futures) {
System.out.println(future.get());
}
}
public static CompletableFuture<Integer> processAsync(int num) {
return CompletableFuture.supplyAsync(() -> {
System.out.println("Processing " + num + " in thread " + Thread.currentThread().getName());
return num * 2;
});
}
}
- 我们首先定义了一个整数数组 nums,然后使用 Java 8 Stream 的 mapToObj 方法对数组中的每个元素进行处理,并使用 CompletableFuture.supplyAsync 方法将处理过程异步化。我们将所有异步任务的 CompletableFuture 对象存储在一个数组中,并使用 CompletableFuture.allOf 方法等待所有异步任务执行完成。最后,我们使用 CompletableFuture.get 方法获取每个异步任务的处理结果,并输出到控制台。
- 在 processAsync 方法中,我们使用 CompletableFuture.supplyAsync 方法将处理过程异步化,并打印了当前处理的元素和线程名称,以便观察异步操作的效果。
结果输出:
Processing 1 in thread ForkJoinPool.commonPool-worker-1
Processing 2 in thread ForkJoinPool.commonPool-worker-2
Processing 3 in thread ForkJoinPool.commonPool-worker-3
Processing 4 in thread ForkJoinPool.commonPool-worker-4
Processing 5 in thread ForkJoinPool.commonPool-worker-5
Processing 6 in thread ForkJoinPool.commonPool-worker-6
Processing 7 in thread ForkJoinPool.commonPool-worker-7
Processing 8 in thread ForkJoinPool.commonPool-worker-8
Processing 9 in thread ForkJoinPool.commonPool-worker-1
Processing 10 in thread ForkJoinPool.commonPool-worker-2
2
4
6
8
10
12
14
16
18
20
- 在异步操作中,所有元素都被分配到了不同的线程中进行处理,从而提高了处理效率
Java CompletableFuture异步操作的示例:
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
public class CompletableFutureDemo {
public static void main(String[] args) throws ExecutionException, InterruptedException {
// 创建一个CompletableFuture对象
CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> {
try {
// 模拟耗时操作
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
return "Hello, CompletableFuture!";
});
// 注册回调函数,当异步操作完成时执行
future.thenAccept(result -> System.out.println(result));
// 阻塞当前线程,等待异步操作完成
String result = future.get();
System.out.println(result);
}
}
- 我们首先创建了一个CompletableFuture对象,使用
supplyAsync
方法执行一个耗时操作。然后我们注册了一个回调函数,在异步操作完成时执行,输出异步操作的结果。最后使用get
方法阻塞当前线程,等待异步操作完成,并输出异步操作的结果。 - 需要注意的是,使用CompletableFuture进行异步操作时,应当避免使用
Thread.sleep
等阻塞方法,否则会影响其他线程的执行。应当使用CompletableFuture.delayedExecutor
等方法实现延迟执行。
CompletableFuture 和 CompletableFuture.delayedExecutor 方法
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.TimeUnit;
public class CompletableFutureDemo {
public static void main(String[] args) {
CompletableFuture<Void> future = CompletableFuture.runAsync(() -> {
// 执行异步任务
System.out.println("异步任务开始执行...");
try {
TimeUnit.SECONDS.sleep(3);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("异步任务执行完成!");
}, CompletableFuture.delayedExecutor(5, TimeUnit.SECONDS)); // 延迟 5 秒执行
System.out.println("主线程继续执行...");
future.join(); // 等待异步任务执行完成
}
}
- 上面的示例中,我们使用 CompletableFuture.runAsync 方法创建了一个异步任务,并使用 CompletableFuture.delayedExecutor 方法来延迟 5 秒执行该任务。在主线程中,我们打印了一条消息,然后使用 future.join() 方法等待异步任务执行完成 ,
输出结果:
主线程继续执行...
异步任务开始执行...
异步任务执行完成!
- 可以看到,异步任务在延迟 5 秒后开始执行,而主线程在异步任务执行期间继续执行。这就是异步编程的优势之一:可以在执行耗时的操作时不阻塞主线程,从而提高程序的并发性和响应性。