【Future&ForkJoin框架原理】

简介: 【Future&ForkJoin框架原理】

Future&ForkJoin框架原理

Future:

Future是一种异步计算机制,可以在一个线程中提交一个任务,并在另一线程中的某个时候获取该任务的结果。Future提供了一个get方法,该方法会阻塞调用线程直到计算结果可用。Future还提供了isDone方法,用于检查计算是否已经完成。

示例代码:

ExecutorService executor = Executors.newSingleThreadExecutor();
Future<Integer> future = executor.submit(() -> {
    // 模拟长时间计算
    Thread.sleep(3000);
    return 100;
});
System.out.println("等待计算结果...");
while (!future.isDone()) {
    // 等待计算结果
}
System.out.println("计算结果为:" + future.get());
executor.shutdown();

在上面的示例中,我们创建了一个ExecutorService,然后提交了一个Callable任务,该任务会休眠3秒钟,然后返回整数100。我们使用Future的get方法等待任务完成并获取结果。可以看到,在等待任务完成时,调用线程会一直被阻塞。

ForkJoin框架:

ForkJoin框架是一种并行计算框架,自JDK1.7引入以来,已经成为Java并发编程中的重要组成部分。ForkJoin框架通过将大任务拆分为小任务,然后在不同的线程中并行执行这些小任务,最终将所有的小任务结果合并得到最终结果。

ForkJoin框架中有两个重要的类:ForkJoinPool和ForkJoinTask。ForkJoinPool是一个特殊的线程池,用于执行ForkJoinTask。ForkJoinTask表示可以被拆分为更小任务的任务。ForkJoinTask有两种类型:RecursiveTask和RecursiveAction。RecursiveTask表示有返回值的任务,而RecursiveAction表示没有返回值的任务。

示例代码:

class SumTask extends RecursiveTask<Long> {
    private static final int THRESHOLD = 10000;
    private final int[] array;
    private final int start;
    private final int end;
    SumTask(int[] array, int start, int end) {
        this.array = array;
        this.start = start;
        this.end = end;
    }
    @Override
    protected Long compute() {
        if (end - start <= THRESHOLD) {
            long sum = 0;
            for (int i = start; i < end; i++) {
                sum += array[i];
            }
            return sum;
        } else {
            int middle = (start + end) >>> 1;
            SumTask leftTask = new SumTask(array, start, middle);
            SumTask rightTask = new SumTask(array, middle, end);
            leftTask.fork();
            rightTask.fork();
            return leftTask.join() + rightTask.join();
        }
    }
}
public static void main(String[] args) {
    int[] array = new int[100000];
    for (int i = 0; i < array.length; i++) {
        array[i] = i + 1;
    }
    ForkJoinPool pool = new ForkJoinPool();
    long startTime = System.currentTimeMillis();
    long result = pool.invoke(new SumTask(array, 0, array.length));
    long endTime = System.currentTimeMillis();
    System.out.println("计算结果为:" + result);
    System.out.println("耗时:" + (endTime - startTime) + "毫秒");
    pool.shutdown();
}

在上面的示例中,我们创建了一个有10万个元素的整数数组,然后创建了一个SumTask,该任务用于计算数组中所有元素的和。如果数组的长度小于等于阈值10000,我们直接计算结果并返回;否则,我们将数组拆分为两个子数组,分别创建任务计算子数组的和,并使用fork方法将任务提交到ForkJoinPool中。最后,我们使用join方法获取子任务的计算结果,并将结果进行合并。可以看到,在ForkJoin框架中,我们使用更少的代码实现了并行计算,同时也减少了很多线程同步的开销。

小故事

有一个农夫需要在他的田地里种植许多植物。为了尽快完成这项任务,他决定雇佣一些工人帮他。他将他的田地划分成许多小块,并为每个工人分配了一个小块来种植。每个工人都可以在他们的小块周围挖掘土壤,种下植物,并且记录他们的进度。

Future框架就像雇佣工人一样,它将任务划分成小部分并分配给不同的线程来处理。在我们的故事中,每个工人都在记录自己的进度,这就是Future的关键:每个线程都可以记录自己的进度并返回自己的结果给主线程。

那么,ForkJoin框架又是什么呢?它就像一个老板,会监督所有的工作并确定每个线程的进度。在我们的故事中,老板在收集工人的报告时会确定哪个区域已经完成,哪些工人需要帮助他们完成他们的任务。ForkJoin框架也是这样,它会监督所有任务的执行并决定是否需要fork新的任务,并将它们分配给其他线程来处理。

总的来说,Future和ForkJoin框架结合起来可以将大型任务分成小的部分,并同时利用多个线程来处理任务,从而提高系统的效率和响应速度。

相关文章
|
6月前
|
缓存 Java 调度
Java并发编程学习10-任务执行与Executor框架
【4月更文挑战第12天】本篇 重点讲解任务执行和 Executor框架的基础知识
62 4
Java并发编程学习10-任务执行与Executor框架
|
4月前
|
缓存 Java 调度
Java并发编程:深入解析线程池与Future任务
【7月更文挑战第9天】线程池和Future任务是Java并发编程中非常重要的概念。线程池通过重用线程减少了线程创建和销毁的开销,提高了资源利用率。而Future接口则提供了检查异步任务状态和获取任务结果的能力,使得异步编程更加灵活和强大。掌握这些概念,将有助于我们编写出更高效、更可靠的并发程序。
|
3月前
|
Java
Future原理解析
介绍了Java多线程中Future类的原理
Future原理解析
|
4月前
|
Java 开发者
Java并发编程之Executor框架详解
【7月更文挑战第18天】本文旨在深入探讨Java中的Executor框架,揭示其对并发编程的优化作用。通过解析Executor接口、ThreadPoolExecutor和ScheduledExecutorService等关键组件,文章展示了如何有效管理和控制线程资源。同时,结合实例分析,本文阐释了Executor框架在提高程序性能、简化代码结构方面的实际应用价值。旨在为Java开发者提供并发编程的高级工具,帮助他们构建更加高效、稳定的多线程应用。
|
6月前
|
前端开发 JavaScript Java
每日一博 - Java 异步编程的 Promise 模式 CompletableFuture的前世今生 (上)
每日一博 - Java 异步编程的 Promise 模式 CompletableFuture的前世今生 (上)
201 0
每日一博 - Java 异步编程的 Promise 模式 CompletableFuture的前世今生 (上)
|
6月前
|
并行计算 算法 Java
Java线程池——Executor框架
Executor 框架是 Java5 之后引进的,在 Java 5 之后,通过 Executor 来启动线程比使用 Thread 的 start 方法更好,除了更易管理,效率更好(用线程池实现,节约开销)。 Executor 框架不仅包括了线程池的管理,还提供了线程工厂、队列以及拒绝策略等,Executor 框架让并发编程变得更加简单。
|
存储 Java
并发编程系列教程(09) - Callable与Future模式
并发编程系列教程(09) - Callable与Future模式
55 0
|
Java
异步编程 - 04 基于JDK中的Future实现异步编程(上)_Future & FutureTask 源码解析
异步编程 - 04 基于JDK中的Future实现异步编程(上)_Future & FutureTask 源码解析
74 0
|
Java
异步编程 - 06 基于JDK中的Future实现异步编程(中)_CompletableFuture源码解析
异步编程 - 06 基于JDK中的Future实现异步编程(中)_CompletableFuture源码解析
62 0
|
Java
异步编程 - 07 基于JDK中的Future实现异步编程(下)_当Stream遇见CompletableFuture
异步编程 - 07 基于JDK中的Future实现异步编程(下)_当Stream遇见CompletableFuture
69 0