You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Java多线程随机数求和问题:5线程各生成1数但求和失效

问题分析与修复方案

咱们先来拆解下你的代码里导致求和失效的核心问题:

关键问题梳理

  • 局部变量覆盖实例变量:你的add方法里定义了参数int a,这会直接覆盖类中的实例变量a。同步块里执行的a += n其实是在修改这个局部变量,完全没触及用来累加的实例变量,等于做了无用功。
  • 基本类型值传递陷阱:main方法里的sum是基本类型int,传给summing构造函数时是复制了一份值,所以summing实例里的a和main的sum是完全独立的两个变量,就算实例里的累加逻辑正常,main里的sum也永远是0。
  • 未等待线程执行完成:main启动线程后直接结束,JVM可能在子线程还没完成计算时就退出了,你根本看不到最终的累加结果。

修复后的代码实现

方式一:手动同步保证线程安全

先修改summing类,把累加逻辑绑定到实例变量上,并提供结果获取方法:

import java.util.Random;

public class Summing implements Runnable {
    // 用实例变量作为共享累加容器
    private int total;

    public Summing() {
        this.total = 0;
    }

    @Override
    public void run() {
        generateAndAddRandomNumber();
    }

    private void generateAndAddRandomNumber() {
        Random rand = new Random();
        int n = rand.nextInt(10) + 1;
        System.out.println("Number generated: " + n);
        // 同步块锁定当前实例,保证累加操作原子性
        synchronized (this) {
            total += n;
        }
    }

    // 线程安全的结果获取方法
    public synchronized int getTotal() {
        return total;
    }
}

再修改main方法,等待所有线程执行完成后再打印结果:

public class Main {
    public static void main(String[] args) throws InterruptedException {
        Summing sumCalculator = new Summing();
        
        Thread t1 = new Thread(sumCalculator);
        Thread t2 = new Thread(sumCalculator);
        Thread t3 = new Thread(sumCalculator);
        Thread t4 = new Thread(sumCalculator);
        Thread t5 = new Thread(sumCalculator);
        
        t1.start();
        t2.start();
        t3.start();
        t4.start();
        t5.start();
        
        // 等待所有子线程执行完毕
        t1.join();
        t2.join();
        t3.join();
        t4.join();
        t5.join();
        
        // 输出最终求和结果
        System.out.println("Final sum: " + sumCalculator.getTotal());
    }
}

方式二:用AtomicInteger简化线程安全(推荐)

如果不想手动处理同步逻辑,可以用Java并发包提供的AtomicInteger,它本身就是线程安全的原子类,无需额外加锁:

import java.util.Random;
import java.util.concurrent.atomic.AtomicInteger;

public class Summing implements Runnable {
    private AtomicInteger total = new AtomicInteger(0);

    @Override
    public void run() {
        Random rand = new Random();
        int n = rand.nextInt(10) + 1;
        System.out.println("Number generated: " + n);
        // 原子性累加操作,自带线程安全
        total.addAndGet(n);
    }

    public int getTotal() {
        return total.get();
    }
}

main方法和上面一致,通过join()等待所有线程完成后调用getTotal()即可。

修复逻辑说明

  • 改用实例变量作为共享累加容器,让所有线程操作同一个变量,保证数据能正确累加。
  • 用join()让主线程等待子线程全部执行完毕,确保计算完成后再获取结果。
  • 无论是手动同步还是AtomicInteger,都避免了多线程下的竞态条件,保证累加操作的原子性。

内容的提问来源于stack exchange,提问作者Yoav Linder

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.15 03:30:41