使用fork-join执行长时间运行的任务几乎与单线程程序花费相同的时间

时间:2018-12-25 15:59:11

标签: java performance concurrency fork-join

我正在尝试转换长度为10,00,00,000的数组的每个元素。我的第一种方法是在简单的main方法中使用单个线程。 我的下一个方法是使用Java的fork-join框架,方法是将数组分成10,00,000个块。但是两种方法转换阵列所花费的总时间几乎相同。

public class SerialComputation {

    public static void main(String[] args) {
        Integer[] array = new Integer[100000000];

        for (int i = 0; i < array.length; i++) {
            array[i] = new Random().nextInt(100);
        }
        System.out.println("First 10 elements before transformation:");
        Arrays.asList(array).stream().limit(10).forEach(d -> System.out.print(d + " "));
        System.out.println();

        long startTime = System.currentTimeMillis();
        for (int i = 0; i < array.length; i++) {
            array[i] *= 2;
        }
        long endTime = System.currentTimeMillis();
        System.out.println("First 10 elements after transformation:");
        Arrays.asList(array).stream().limit(10).forEach(d -> System.out.print(d + " "));
        System.out.println();
        System.out.println("Total time taken: " + (endTime - startTime));
    }   
}


class ParallelComputation {
    public static void main(String[] args) {
        Integer[] array = new Integer[100000000];

        for (int i = 0; i < array.length; i++) {
            array[i] = new Random().nextInt(100);
        }
        System.out.println("First 10 elements before transformation:");
        Arrays.asList(array).stream().limit(10).forEach(d -> System.out.print(d + " "));
        System.out.println();

        ForkJoinTask<?> forkJoinTask = new TransformTask(0, array.length, array);
        ForkJoinPool pool = new ForkJoinPool();
        long startTime = System.currentTimeMillis();
        pool.invoke(forkJoinTask);
        long endTime = System.currentTimeMillis();

        System.out.println("First 10 elements after transformation:");
        Arrays.asList(array).stream().limit(10).forEach(d -> System.out.print(d + " "));
        System.out.println("Total time taken: " + (endTime - startTime));
    }
}

class TransformTask extends RecursiveAction {

    private static final long serialVersionUID = 1L;
    private int start;
    private int end;
    private Integer[] array;

    public TransformTask(int start, int end, Integer[] array) {
        this.start = start;
        this.end = end;
        this.array = array;
    }

    @Override
    protected void compute() {

        if (end - start <= 1000000) {
            for (int i = start; i < end; i++) {
                array[i] *= 2;
            }
        } else {
            int middle = start + ((end - start) / 2);
            System.out.println("start:" + start + "middle:" + middle + "end:" + end);
            invokeAll(new TransformTask(start, middle, array), new TransformTask(middle, end, array));
        }  
    }  
}

我期望ParallelComputation的计算结果比SerialComputation快得多。但是,两者几乎都在同时完成这项工作。 我正在使用带有Windows 10的Intel Core i7处理器的机器。

1 个答案:

答案 0 :(得分:0)

我无法评论TransformTask的实现,但这是

static long parallelStreamComputation() {

    Integer[] array = new Integer[100000000];

    for (int i = 0; i < array.length; i++) {
        array[i] = new Random().nextInt(100);
    }

    long startTime = System.currentTimeMillis();
    Arrays.stream(array).parallel().mapToInt( i -> i*2).toArray();
    long endTime = System.currentTimeMillis();
    return endTime-startTime;
}

测得速度要快10倍左右。