并发编程- 线程池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))+"毫秒");

    }
}

执行结果

相关推荐
Forget the Dream1 小时前
设计模式之迭代器模式
java·c++·设计模式·迭代器模式
大丈夫在世当日食一鲲1 小时前
Java中用到的设计模式
java·开发语言·设计模式
A-Kamen1 小时前
Spring Boot拦截器(Interceptor)与过滤器(Filter)深度解析:区别、实现与实战指南
java·spring boot·后端
练川1 小时前
Stream特性(踩坑):惰性执行、不修改原始数据源
java·stream
狂奔小菜鸡1 小时前
Java运行时数据区
java·jvm·后端
trymoLiu1 小时前
SpringBoot 实现 RSA+AES 自动接口解密!
java·spring boot
ChinaRainbowSea2 小时前
MySQL 索引的数据结构(详细说明)
java·数据结构·数据库·后端·mysql
33三 三like2 小时前
软件工程画图题
java·开发语言·软件工程
去看全世界的云2 小时前
【Kotlin】Kotlin基础笔记
android·java·笔记·kotlin
tangweiguo030519872 小时前
Android打造易用的 WiFi 工具类:WifiUtils 封装实践
android·java·wifi