并行执行求和问题 returns 意想不到的结果

Parallel implementation of sum problem returns unexpected results

所以我正在学习和试验 java 并发包,在那里我发现了一个并行实现的加法运算。

我想尝试不同的方法,所以我混合了合并排序算法的并行实现,即分而治之的方法与典型的数字加法。

代码如下:

class SequentialSum {
    public static long sum(int[] numbers, int low, int high) {
        long total = 0;
        for (int i = low; i <= high; i++) total += numbers[i];
        return total;
    }
}

class ParallelSum {

    private static final AtomicLong finalSum = new AtomicLong(0);

    public static void parallelSum(int[] numbers, int low, int high, int threads) {

        if (threads <= 1) finalSum.addAndGet(SequentialSum.sum(numbers, low, high));

        int middle = (low + high) / 2;
        Thread left = new Thread(() -> parallelSum(numbers, low, middle, threads / 2));
        Thread right = new Thread(() -> parallelSum(numbers, middle + 1, high, threads / 2));

        left.start();
        right.start();
    }

    public static long getOutput() {
        return finalSum.get();
    }
}

public class _3_ParallelSummation {

    private static final int NUM_OF_THREADS = Runtime.getRuntime().availableProcessors();
    private static final Random random = new Random();
    private static final int ARRAY_LENGTH = 100_000_000;

    public static void main(String[] args) throws InterruptedException {

        int[] numbers = new int[ARRAY_LENGTH];
        for (int i = 0; i < ARRAY_LENGTH; i++) numbers[i] = random.nextInt(10);


        long t1 = System.currentTimeMillis();
        long sum = SequentialSum.sum(numbers, 0, ARRAY_LENGTH - 1);
        long t2 = System.currentTimeMillis();
        System.out.printf("Sum is: %d, completed in %d ms\n", sum, t2 - t1);

        t1 = System.currentTimeMillis();
        ParallelSum.parallelSum(numbers, 0, ARRAY_LENGTH - 1, NUM_OF_THREADS);
        t2 = System.currentTimeMillis();
        Thread.sleep(1000);
        System.out.printf("Sum is: %d, completed in %d ms\n", ParallelSum.getOutput(), t2 - t1);
    }
}

我得到了意想不到的结果:

Sum is: 449963052, completed in 56 ms
Sum is: 3950670566, completed in 3 ms
[28.597s][warning][os,thread] Failed to start thread - _beginthreadex failed (EACCES) for attributes: stacksize: default, flags: CREATE_SUSPENDED STACK_SIZE_PARAM_IS.
[28.598s][warning][os,thread] Failed to start thread - _beginthreadex failed (EACCES) for attributes: stacksize: default, flags: CREATE_SUSPENDED STACK_SIZE_PARAM_IS.
[28.598s][warning][os,thread] Failed to start thread - _beginthreadex failed (EACCES) for attributes: stacksize: default, flags: CREATE_SUSPENDED STACK_SIZE_PARAM_IS.
[28.601s][warning][os,thread] Failed to start thread - _beginthreadex failed (EACCES) for attributes: stacksize: default, flags: CREATE_SUSPENDED STACK_SIZE_PARAM_IS.

我的代码有什么错误?还是我的思路不对?

合并排序中缺少 else 块

if (threads <= 1) { 
            finalSum.addAndGet(SequentialSum.sum(numbers, low, high));
        }else {
        int middle = (low + high) / 2;
        Thread left = new Thread(() -> parallelSum(numbers, low, middle, threads / 2));
        Thread right = new Thread(() -> parallelSum(numbers, middle + 1, high, threads / 2));
        left.start();
        right.start();
}

添加 else 块将修复代码。

您也可以使用join()

移除固定睡眠时间
left.join();
right.join();