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

数据结构加油站:

Comparison Sorting Visualization

并发设计模式

单线程归并排序

java 复制代码
public class MergeSort {

    private final int[] arrayToSort; //要排序的数组
    private final int threshold;  //拆分的阈值,低于此阈值就不再进行拆分

    public MergeSort(final int[] arrayToSort, final int threshold) {
        this.arrayToSort = arrayToSort;
        this.threshold = threshold;
    }

    /**
     * 排序
     * @return
     */
    public int[] mergeSort() {
        return mergeSort(arrayToSort, threshold);
    }

    public static int[] mergeSort(final int[] arrayToSort, int threshold) {
        //拆分后的数组长度小于阈值,直接进行排序
        if (arrayToSort.length < threshold) {
            //调用jdk提供的排序方法
            Arrays.sort(arrayToSort);
            return arrayToSort;
        }

        int midpoint = arrayToSort.length / 2;
        //对数组进行拆分
        int[] leftArray = Arrays.copyOfRange(arrayToSort, 0, midpoint);
        int[] rightArray = Arrays.copyOfRange(arrayToSort, midpoint, arrayToSort.length);
        //递归调用
        leftArray = mergeSort(leftArray, threshold);
        rightArray = mergeSort(rightArray, threshold);
        //合并排序结果
        return merge(leftArray, rightArray);
    }

    public static int[] merge(final int[] leftArray, final int[] rightArray) {
        //定义用于合并结果的数组
        int[] mergedArray = new int[leftArray.length + rightArray.length];
        int mergedArrayPos = 0;
        // 利用双指针进行两个数的比较
        int leftArrayPos = 0;
        int rightArrayPos = 0;
        while (leftArrayPos < leftArray.length && rightArrayPos < rightArray.length) {
            if (leftArray[leftArrayPos] <= rightArray[rightArrayPos]) {
                mergedArray[mergedArrayPos] = leftArray[leftArrayPos];
                leftArrayPos++;
            } else {
                mergedArray[mergedArrayPos] = rightArray[rightArrayPos];
                rightArrayPos++;
            }
            mergedArrayPos++;
        }

        while (leftArrayPos < leftArray.length) {
            mergedArray[mergedArrayPos] = leftArray[leftArrayPos];
            leftArrayPos++;
            mergedArrayPos++;
        }

        while (rightArrayPos < rightArray.length) {
            mergedArray[mergedArrayPos] = rightArray[rightArrayPos];
            rightArrayPos++;
            mergedArrayPos++;
        }

        return mergedArray;
    }

forkjoin排序

java 复制代码
/**
 * 利用fork-join实现数组排序
 */
public class MergeSortTask extends RecursiveAction {

	private final int threshold; //拆分的阈值,低于此阈值就不再进行拆分
	private int[] arrayToSort; //要排序的数组

	public MergeSortTask(final int[] arrayToSort, final int threshold) {
		this.arrayToSort = arrayToSort;
		this.threshold = threshold;
	}

	@Override
	protected void compute() {
		//拆分后的数组长度小于阈值,直接进行排序
		if (arrayToSort.length <= threshold) {
			// 调用jdk提供的排序方法
			Arrays.sort(arrayToSort);
			return;
		}

		// 对数组进行拆分
		int midpoint = arrayToSort.length / 2;
		int[] leftArray = Arrays.copyOfRange(arrayToSort, 0, midpoint);
		int[] rightArray = Arrays.copyOfRange(arrayToSort, midpoint, arrayToSort.length);

		MergeSortTask leftTask = new MergeSortTask(leftArray, threshold);
		MergeSortTask rightTask = new MergeSortTask(rightArray, threshold);

		//调用任务,阻塞当前线程,直到所有子任务执行完成
		invokeAll(leftTask,rightTask);
		//提交任务
//		leftTask.fork();
//		rightTask.fork();
//		//合并结果
//		leftTask.join();
//		rightTask.join();

		// 合并排序结果
		arrayToSort = MergeSort.merge(leftTask.getSortedArray(), rightTask.getSortedArray());
	}

	public int[] getSortedArray() {
		return arrayToSort;
	}

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

java 复制代码
public class Utils {

	/**
	 * 随机生成数组
	 * @param size 数组的大小
	 * @return
	 */
	public static int[] buildRandomIntArray(final int size) {
		int[] arrayToCalculateSumOf = new int[size];
		Random generator = new Random();
		for (int i = 0; i < arrayToCalculateSumOf.length; i++) {
			arrayToCalculateSumOf[i] = generator.nextInt(100000000);
		}
		return arrayToCalculateSumOf;
	}
}

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

java 复制代码
public class ArrayToSortMain {

    public static void main(String[] args) {
        //生成测试数组  用于归并排序
        int[] arrayToSortByMergeSort = Utils.buildRandomIntArray(20000000);
        //生成测试数组  用于forkjoin排序
        int[] arrayToSortByForkJoin = Arrays.copyOf(arrayToSortByMergeSort, arrayToSortByMergeSort.length);
        //获取处理器数量
        int processors = Runtime.getRuntime().availableProcessors();


        MergeSort mergeSort = new MergeSort(arrayToSortByMergeSort, processors);
        long startTime = System.nanoTime();
        // 归并排序
        mergeSort.mergeSort();
        long duration = System.nanoTime()-startTime;
        System.out.println("单线程归并排序时间: "+(duration/(1000f*1000f))+"毫秒");

        //利用forkjoin排序
        MergeSortTask mergeSortTask = new MergeSortTask(arrayToSortByForkJoin, processors);
        //构建forkjoin线程池
        ForkJoinPool forkJoinPool = new ForkJoinPool(processors);
        startTime = System.nanoTime();
        //执行排序任务
        forkJoinPool.invoke(mergeSortTask);
        duration = System.nanoTime()-startTime;
        System.out.println("forkjoin排序时间: "+(duration/(1000f*1000f))+"毫秒");

    }
}

执行结果

相关推荐
李可以量化38 分钟前
Tornado 从了解到精通(一)下:异步与非阻塞 IO 核心原理
java·数据库·tornado
yurenpai(27届找实习中)39 分钟前
从销售订单推送 MES 看懂微服务调用(二):DTO 转换与 OpenFeign 调用
java·微服务·架构·服务调用
Patrick在香港1 小时前
Python爬虫框架实战:优雅抓取香港政府公开API数据的通用方案
java·开发语言·爬虫·python·ai编程·数据可视化·可用性测试
hey_sml1 小时前
MySQL常用操作速记:从字符集到游标全解析
java·开发语言·mysql
掉鱼的猫1 小时前
Solon AOT & Native:三段式编译,从 Java 到原生可执行文件
java·云原生
Java内核笔记1 小时前
容错能力进入 spring-core:Spring Boot 4 原生重试机制全解析
java·后端
未秃头的程序猿1 小时前
虚拟线程上线一周后翻车了——pinning问题排查实录
java·后端·架构
wuminyu1 小时前
JDK21解决虚拟线程IO阻塞原理剖析
java·linux·c语言·jvm·c++
带刺的坐椅1 小时前
Solon AOT & Native:三段式编译,从 Java 到原生可执行文件
java·aot·solon·native
程序员良辰1 小时前
【TongWeb8】使用 Crontab 定时重启和检测 TongWeb 服务
java·中间件·tomcat