Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/multithreading/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java:两个线程同时对给定范围内的数字求和:当只有一个线程连接到第二个线程时';s的总数太大了_Java_Multithreading_Concurrency - Fatal编程技术网

Java:两个线程同时对给定范围内的数字求和:当只有一个线程连接到第二个线程时';s的总数太大了

Java:两个线程同时对给定范围内的数字求和:当只有一个线程连接到第二个线程时';s的总数太大了,java,multithreading,concurrency,Java,Multithreading,Concurrency,我有两个线程在单个整数数组中求和:[0;100\u 000]。 每个线程都是一个对象,它有min、max和sum字段,我稍后通过对两个线程的结果求和来获得总和。 线程1对[0,20\u 000]范围内的数字求和,而线程2对[20\u 001,100\u 000]范围内的数字求和。正确的thread1的和是200010000,正确的thread2的和是505072704,正确的[01100\u 000]范围内的数字总和是705082704 当两个线程都连接到主方法的线程内时,它工作正常。但是,如果

我有两个线程在单个整数数组中求和:
[0;100\u 000]
。 每个线程都是一个对象,它有
min、max
sum
字段,我稍后通过对两个线程的结果求和来获得总和。 线程1对
[0,20\u 000]
范围内的数字求和,而线程2对
[20\u 001,100\u 000]
范围内的数字求和。正确的thread1的和是
200010000
,正确的thread2的和是
505072704
,正确的
[01100\u 000]
范围内的数字总和是
705082704

当两个线程都连接到主方法的线程内时,它工作正常。但是,如果我只加入第一个线程,那么main方法将在第二个线程完成之前继续打印结果。我理解这种行为。但是,我不明白为什么在这些结果中(此时thread1已完成且其总和正确,而thread2尚未完成且其总和不正确),thread2的总和超过其最大可能总和(
505072704
)。我不明白这怎么可能

public class SumNumbers {
    public static void main(String[] args) throws Exception {
        int min = 0;
        int max = 100_000;

        int left = 20_000;
        int right = 100_000;

        int usualSum = 0;
        for (int i = min; i<= max; i++)  {
            usualSum += i;
        }
        System.out.printf("usual sum: %,d\n", usualSum);

        SummerThread s1 = new SummerThread(0, left);
        SummerThread s2 = new SummerThread(left + 1, right);

        Thread thread1 = new Thread(s1, "left thread");
        Thread thread2 = new Thread(s2, "right thread");

        thread1.start();
        thread2.start();

        thread1.join();
       // thread2.join();

        System.out.printf("left sum: %,d\n", s1.getSum());
        System.out.printf("right sum: %,d\n", s2.getSum());
        System.out.printf("left + right: %,d\n", s1.getSum() + s2.getSum());

        thread2.join();
        System.out.printf("right sum: %,d\n", s2.getSum());
        System.out.printf("left + right: %,d\n", s1.getSum() + s2.getSum());

    }
}

class SummerThread implements Runnable  {


    private int sum;
    private int min;
    private int max;

    private int id;
    private static int count;

    public SummerThread(int min, int max)  {
        this.min = min;
        this.max = max;

        count++;
        id = count;
    }

    @Override
    public void run()  {
        for (int i = min; i <= max; i++)  {
           // System.out.println("thread: " + id);
            sum += i;
        }
    }

    public int getSum()  {return sum;}
}
正确的输出(如果所有
.join
均未注释)为:


你的数学不是在这儿吗?从1到n的总和是
n(n+1)/2
,如果将
n
替换为
100000
,则得到
5000050000
。这超过了可以存储在
int
中的最大数量,约为20亿。部分和高于最终和的原因可能是您遇到了整数溢出

为了说明这一点,下面的代码片段很有用:

System.out.println((int) 5_000_050_000L); // prints 705082704

如您所见,我们再次找到了您的705082704和,但它是不正确的,只得到下面整数的结果。

您的数学不是在这里吗?从1到n的总和是
n(n+1)/2
,如果将
n
替换为
100000
,则得到
5000050000
。这超过了可以存储在
int
中的最大数量,约为20亿。部分和高于最终和的原因可能是您遇到了整数溢出

为了说明这一点,下面的代码片段很有用:

System.out.println((int) 5_000_050_000L); // prints 705082704

正如您所看到的,我们再次找到了您的705082704和,但它是不正确的,仅由下面的整数得出。

谢谢!我完全没有意识到正确的总数实际上是不同的!我将所有
int
替换为
long
无问题。为了使代码更加安全,您可以做一些类似的操作,如在循环中(sum>Long.MAX\u VALUE-i)抛出…,这样可以防止溢出
stricmath。addExact(x,y)
可能更好。很好,我不知道这一点谢谢!我完全没有意识到正确的总数实际上是不同的!我将所有
int
替换为
long
无问题。为了使代码更加安全,您可以做一些类似的事情,比如在循环中(sum>Long.MAX\u VALUE-i)抛出…,这样可以防止溢出
stricmath.addExact(x,y)
可能更好。很好,我不知道这一点
usual sum: 705,082,704
left sum: 200,010,000
right sum: 1,625,006,320
left + right: 1,825,016,320
right sum: 505,072,704
left + right: 705,082,704
usual sum: 705,082,704
left sum: 200,010,000
right sum: 505,072,704
left + right: 705,082,704
right sum: 505,072,704
left + right: 705,082,704
System.out.println((int) 5_000_050_000L); // prints 705082704