[Java实现异步编程 合集]

 

目录

前言:

异步编程相关实现方式:

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 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 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[] futures = Arrays.stream(nums)
                .mapToObj(StreamAsyncDemo::processAsync)
                .toArray(CompletableFuture[]::new);

        CompletableFuture.allOf(futures).join();

        for (CompletableFuture future : futures) {
            System.out.println(future.get());
        }
    }

    public static CompletableFuture 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 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 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 秒后开始执行,而主线程在异步任务执行期间继续执行。这就是异步编程的优势之一:可以在执行耗时的操作时不阻塞主线程,从而提高程序的并发性和响应性。

你可能感兴趣的:(java,开发语言)