问题一:在下面的示例代码中,为什么要使用join()方法?它的作用是什么?
在下面的示例代码中,为什么要使用join()方法?它的作用是什么?
package learning.multithreading; import java.util.Random;import java.util.concurrent.ExecutionException;import java.util.concurrent.ForkJoinPool;import java.util.concurrent.RecursiveTask; public class ParallelSumComputationUsingForkJoin { private static final int[] LARGE_ARR = largeArr(); private static final int LENGTH = LARGE_ARR.length; public static void main(String[] args) throws ExecutionException, InterruptedException { RecursiveSumTask recursiveTask = new RecursiveSumTask(0, LENGTH, LARGE_ARR); ForkJoinPool forkJoinPool = ForkJoinPool.commonPool(); long start = System.currentTimeMillis(); long sum = forkJoinPool.invoke(recursiveTask); System.out.println("The sum is : " + sum + ", Time Taken by Parallel(Fork/Join) Execution: " + (System.currentTimeMillis() - start) + " millis"); } private static int[] largeArr() { return new Random().ints(500000000, 10, 1000).toArray(); } static class RecursiveSumTask extends RecursiveTask<Long> { private static final int SEQUENTIAL_COMPUTE_THRESHOLD = 4000; private final int startIndex; private final int endIndex; private final int[] data; RecursiveSumTask(int startIndex, int endIndex, int[] data) { this.startIndex = startIndex; this.endIndex = endIndex; this.data = data; } @Override protected Long compute() { if (SEQUENTIAL_COMPUTE_THRESHOLD >= (endIndex - startIndex)) { long sum = 0; for (int i = startIndex; i < endIndex; i++) { sum += data[i]; } return sum; } int mid = startIndex + (endIndex - startIndex) / 2; RecursiveSumTask leftSumTask = new RecursiveSumTask(startIndex, mid, data); RecursiveSumTask rightSumTask = new RecursiveSumTask(mid, endIndex, data); leftSumTask.fork(); // Fork the Left Task in a Separate Execution long rightSum = rightSumTask.compute(); // Compute the Right Part long leftSum = leftSumTask.join(); // Wait for the results from the Left Part return leftSum + rightSum; // Return Both } }}/** * Output: * The sum is : 252235235953, Time Taken by Parallel(Fork/Join) Execution: 139 millis *
参考回答:
join()方法被用于等待左侧子任务的完成,并获取其结果。join()是阻塞调用,调用线程会等待左侧子任务执行完成后才继续执行,从而确保在合并结果之前,所有的子任务都已经完成。
关于本问题的更多回答可点击原文查看:
https://developer.aliyun.com/ask/625186
问题二:在下面的示例代码中,SEQUENTIAL_COMPUTE_THRESHOLD变量起什么作用?
在下面的示例代码中,SEQUENTIAL_COMPUTE_THRESHOLD变量起什么作用?
package learning.multithreading; import java.util.Random;import java.util.concurrent.ExecutionException;import java.util.concurrent.ForkJoinPool;import java.util.concurrent.RecursiveTask; public class ParallelSumComputationUsingForkJoin { private static final int[] LARGE_ARR = largeArr(); private static final int LENGTH = LARGE_ARR.length; public static void main(String[] args) throws ExecutionException, InterruptedException { RecursiveSumTask recursiveTask = new RecursiveSumTask(0, LENGTH, LARGE_ARR); ForkJoinPool forkJoinPool = ForkJoinPool.commonPool(); long start = System.currentTimeMillis(); long sum = forkJoinPool.invoke(recursiveTask); System.out.println("The sum is : " + sum + ", Time Taken by Parallel(Fork/Join) Execution: " + (System.currentTimeMillis() - start) + " millis"); } private static int[] largeArr() { return new Random().ints(500000000, 10, 1000).toArray(); } static class RecursiveSumTask extends RecursiveTask<Long> { private static final int SEQUENTIAL_COMPUTE_THRESHOLD = 4000; private final int startIndex; private final int endIndex; private final int[] data; RecursiveSumTask(int startIndex, int endIndex, int[] data) { this.startIndex = startIndex; this.endIndex = endIndex; this.data = data; } @Override protected Long compute() { if (SEQUENTIAL_COMPUTE_THRESHOLD >= (endIndex - startIndex)) { long sum = 0; for (int i = startIndex; i < endIndex; i++) { sum += data[i]; } return sum; } int mid = startIndex + (endIndex - startIndex) / 2; RecursiveSumTask leftSumTask = new RecursiveSumTask(startIndex, mid, data); RecursiveSumTask rightSumTask = new RecursiveSumTask(mid, endIndex, data); leftSumTask.fork(); // Fork the Left Task in a Separate Execution long rightSum = rightSumTask.compute(); // Compute the Right Part long leftSum = leftSumTask.join(); // Wait for the results from the Left Part return leftSum + rightSum; // Return Both } }}/** * Output: * The sum is : 252235235953, Time Taken by Parallel(Fork/Join) Execution: 139 millis *
参考回答:
SEQUENTIAL_COMPUTE_THRESHOLD变量在示例代码中设定了一个阈值,当需要处理的数组元素数量小于这个阈值时,任务将不再进行进一步的拆分,而是直接顺序计算。这是为了避免过度拆分任务造成的额外开销,提高计算效率。
关于本问题的更多回答可点击原文查看:
https://developer.aliyun.com/ask/625188
问题三:ForkJoinTask可以通过哪些方法来提交任务?
ForkJoinTask可以通过哪些方法来提交任务?
参考回答:
可以使用execute()、invoke()和submit()方法来提交任务。
关于本问题的更多回答可点击原文查看:
https://developer.aliyun.com/ask/625189
问题四:ForkJoinPool中任务是如何排队的?
ForkJoinPool中任务是如何排队的?
参考回答:
ForkJoinPool维护一个全局共享队列,所有提交的任务都会在这个共享队列中排队。
关于本问题的更多回答可点击原文查看:
https://developer.aliyun.com/ask/625190
问题五:在ForkJoinPool模型中,工作线程如何从多个来源检查任务?
在ForkJoinPool模型中,工作线程如何从多个来源检查任务?
参考回答:
工作线程会检查来自全局共享队列、本地工作窃取队列以及其他线程的工作窃取队列的任务。
关于本问题的更多回答可点击原文查看: