• 并发编程- 线程池ForkJoinPool工作原理分析(实践)


     数据结构加油站:

    Comparison Sorting Visualization

    并发设计模式

    单线程归并排序

    1. public class MergeSort {
    2. private final int[] arrayToSort; //要排序的数组
    3. private final int threshold; //拆分的阈值,低于此阈值就不再进行拆分
    4. public MergeSort(final int[] arrayToSort, final int threshold) {
    5. this.arrayToSort = arrayToSort;
    6. this.threshold = threshold;
    7. }
    8. /**
    9. * 排序
    10. * @return
    11. */
    12. public int[] mergeSort() {
    13. return mergeSort(arrayToSort, threshold);
    14. }
    15. public static int[] mergeSort(final int[] arrayToSort, int threshold) {
    16. //拆分后的数组长度小于阈值,直接进行排序
    17. if (arrayToSort.length < threshold) {
    18. //调用jdk提供的排序方法
    19. Arrays.sort(arrayToSort);
    20. return arrayToSort;
    21. }
    22. int midpoint = arrayToSort.length / 2;
    23. //对数组进行拆分
    24. int[] leftArray = Arrays.copyOfRange(arrayToSort, 0, midpoint);
    25. int[] rightArray = Arrays.copyOfRange(arrayToSort, midpoint, arrayToSort.length);
    26. //递归调用
    27. leftArray = mergeSort(leftArray, threshold);
    28. rightArray = mergeSort(rightArray, threshold);
    29. //合并排序结果
    30. return merge(leftArray, rightArray);
    31. }
    32. public static int[] merge(final int[] leftArray, final int[] rightArray) {
    33. //定义用于合并结果的数组
    34. int[] mergedArray = new int[leftArray.length + rightArray.length];
    35. int mergedArrayPos = 0;
    36. // 利用双指针进行两个数的比较
    37. int leftArrayPos = 0;
    38. int rightArrayPos = 0;
    39. while (leftArrayPos < leftArray.length && rightArrayPos < rightArray.length) {
    40. if (leftArray[leftArrayPos] <= rightArray[rightArrayPos]) {
    41. mergedArray[mergedArrayPos] = leftArray[leftArrayPos];
    42. leftArrayPos++;
    43. } else {
    44. mergedArray[mergedArrayPos] = rightArray[rightArrayPos];
    45. rightArrayPos++;
    46. }
    47. mergedArrayPos++;
    48. }
    49. while (leftArrayPos < leftArray.length) {
    50. mergedArray[mergedArrayPos] = leftArray[leftArrayPos];
    51. leftArrayPos++;
    52. mergedArrayPos++;
    53. }
    54. while (rightArrayPos < rightArray.length) {
    55. mergedArray[mergedArrayPos] = rightArray[rightArrayPos];
    56. rightArrayPos++;
    57. mergedArrayPos++;
    58. }
    59. return mergedArray;
    60. }

    forkjoin排序

    1. /**
    2. * 利用fork-join实现数组排序
    3. */
    4. public class MergeSortTask extends RecursiveAction {
    5. private final int threshold; //拆分的阈值,低于此阈值就不再进行拆分
    6. private int[] arrayToSort; //要排序的数组
    7. public MergeSortTask(final int[] arrayToSort, final int threshold) {
    8. this.arrayToSort = arrayToSort;
    9. this.threshold = threshold;
    10. }
    11. @Override
    12. protected void compute() {
    13. //拆分后的数组长度小于阈值,直接进行排序
    14. if (arrayToSort.length <= threshold) {
    15. // 调用jdk提供的排序方法
    16. Arrays.sort(arrayToSort);
    17. return;
    18. }
    19. // 对数组进行拆分
    20. int midpoint = arrayToSort.length / 2;
    21. int[] leftArray = Arrays.copyOfRange(arrayToSort, 0, midpoint);
    22. int[] rightArray = Arrays.copyOfRange(arrayToSort, midpoint, arrayToSort.length);
    23. MergeSortTask leftTask = new MergeSortTask(leftArray, threshold);
    24. MergeSortTask rightTask = new MergeSortTask(rightArray, threshold);
    25. //调用任务,阻塞当前线程,直到所有子任务执行完成
    26. invokeAll(leftTask,rightTask);
    27. //提交任务
    28. // leftTask.fork();
    29. // rightTask.fork();
    30. // //合并结果
    31. // leftTask.join();
    32. // rightTask.join();
    33. // 合并排序结果
    34. arrayToSort = MergeSort.merge(leftTask.getSortedArray(), rightTask.getSortedArray());
    35. }
    36. public int[] getSortedArray() {
    37. return arrayToSort;
    38. }

    随机生成一个数组的工具类

    1. public class Utils {
    2. /**
    3. * 随机生成数组
    4. * @param size 数组的大小
    5. * @return
    6. */
    7. public static int[] buildRandomIntArray(final int size) {
    8. int[] arrayToCalculateSumOf = new int[size];
    9. Random generator = new Random();
    10. for (int i = 0; i < arrayToCalculateSumOf.length; i++) {
    11. arrayToCalculateSumOf[i] = generator.nextInt(100000000);
    12. }
    13. return arrayToCalculateSumOf;
    14. }
    15. }

    单线程归并排序 & forkjoin排序  对比

    1. public class ArrayToSortMain {
    2. public static void main(String[] args) {
    3. //生成测试数组 用于归并排序
    4. int[] arrayToSortByMergeSort = Utils.buildRandomIntArray(20000000);
    5. //生成测试数组 用于forkjoin排序
    6. int[] arrayToSortByForkJoin = Arrays.copyOf(arrayToSortByMergeSort, arrayToSortByMergeSort.length);
    7. //获取处理器数量
    8. int processors = Runtime.getRuntime().availableProcessors();
    9. MergeSort mergeSort = new MergeSort(arrayToSortByMergeSort, processors);
    10. long startTime = System.nanoTime();
    11. // 归并排序
    12. mergeSort.mergeSort();
    13. long duration = System.nanoTime()-startTime;
    14. System.out.println("单线程归并排序时间: "+(duration/(1000f*1000f))+"毫秒");
    15. //利用forkjoin排序
    16. MergeSortTask mergeSortTask = new MergeSortTask(arrayToSortByForkJoin, processors);
    17. //构建forkjoin线程池
    18. ForkJoinPool forkJoinPool = new ForkJoinPool(processors);
    19. startTime = System.nanoTime();
    20. //执行排序任务
    21. forkJoinPool.invoke(mergeSortTask);
    22. duration = System.nanoTime()-startTime;
    23. System.out.println("forkjoin排序时间: "+(duration/(1000f*1000f))+"毫秒");
    24. }
    25. }

    执行结果

  • 相关阅读:
    【Vue.js 3.0源码】一文看懂Vue.js 3.0的优化
    php:实现字符串补零str_pad()
    华为OD 身高体重排序(100分)【java】A卷+B卷
    unipush2.0实现APP消息推送(1)
    技术分享 | Selenium多浏览器处理
    汽车发电机三根线接线图图解,发电机调节器怎么接线
    Yolov5斜框检测tensorrt部署(C++)从入门到入坟
    Ubuntu 升级cuda版本与切换
    腾讯云原生安全“3+1”一体化方案发布,重构云上安全防御体系
    ZISUOJ 数据结构--队列及其应用
  • 原文地址:https://blog.csdn.net/weixin_43874650/article/details/134067280