多线程随机数求和

文章通过两种方法展示了如何使用Java的线程池对10000个元素数组进行多线程求和。法一是每个线程计算一部分和并返回结果,主线程再汇总。法二是使用原子变量避免线程安全问题。虽然法二使用了并发机制,但由于CAS操作,它并不是真正的并行,作者认为法一更优。
摘要由CSDN通过智能技术生成

场景

面对一个10000个元素的随机数数组,使用线程池进行多线程求和。

思路

可以开一个容量为10的线程池,将10000个元素分成10个区间,每个线程负责一段区间。具体写法有两种。

法一

  • 每个线程都有返回值,代表所负责的那段区间的元素和,在主线程中拿到每个线程负责的元素和,然后相加得到结果。

代码

import java.util.Random;
import java.util.concurrent.*;

public class ThreadPoolDemo2 {
    public int getNumsum(int index,int[] nums){
        int numsum=0;
        for(int i=index;i<index+1000;++i){
            numsum+=nums[i];
        }
        return numsum;
    }
    public static void main(String[] args) throws ExecutionException, InterruptedException, TimeoutException {
        ThreadPoolDemo2 threadPoolDemo2=new ThreadPoolDemo2();
        int n=10000;
        int[] nums=new int[n];
        Integer trueans=0;
        Integer countnum=0;
        for(int i=0;i<n;++i){
            int num= new Random().nextInt(100);
            nums[i]=num;
            trueans+=num;
        }
        ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(
                10,20,5, TimeUnit.SECONDS,
                new ArrayBlockingQueue<>(10),
                Executors.defaultThreadFactory(),
                new ThreadPoolExecutor.AbortPolicy()
        );
        for(int i=0;i<10;++i){
            final int index=i;
            Future<Integer> td = threadPoolExecutor.submit(new Callable<Integer>() {
                @Override
                public Integer call() throws Exception {
                    return threadPoolDemo2.getNumsum(index*1000,nums);
                }
            });
            countnum+=td.get();
        }
        threadPoolExecutor.shutdown();
        System.out.println("真实和:"+trueans);
        System.out.println("多线程和:"+countnum);
    }
}

法二

  • 一个全局变量保存结果,每个线程都操作这个全局变量。这样的话很明显会出现线程安全问题,加锁呢又不合适,都使用线程池了不就是寻求并行操作吗,那加锁就不合适了。这里因为操作的是一个变量因此可以使用原子变量去解决。底层是CAS,但也不是真正的并行,总体来说还是法一好。

代码

import java.util.Random;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.Executors;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;

public class ThreadPoolDemo {
    volatile AtomicInteger numsum=new AtomicInteger();

    public void getNumsum(int index,int[] nums){
        for(int i=index;i<index+1000;++i){
            numsum.addAndGet(nums[i]);
        }
    }
    public static void main(String[] args) throws InterruptedException {
        ThreadPoolDemo demo=new ThreadPoolDemo();
        int n=10000;
        int[] nums=new int[n];
        int trueans=0;
        for(int i=0;i<n;++i){
            int num= new Random().nextInt(100);
            nums[i]=num;
            trueans+=num;
        }
        ThreadPoolExecutor tpe=new ThreadPoolExecutor(
                10,
                20,
                5,
                TimeUnit.SECONDS,
                new ArrayBlockingQueue<>(10),
                Executors.defaultThreadFactory(),
                new ThreadPoolExecutor.AbortPolicy()
        );
        for(int i=0;i<10;++i){
            final int idx=i;
            tpe.execute(new Runnable() {
                @Override
                public void run() {
                    demo.getNumsum(idx*1000,nums);
                }
            });
        }
        tpe.shutdown();
        Thread.sleep(300);//这里要延时一下,防止线程还没结束就输出了。
        System.out.println("真实和:"+trueans);
        System.out.println("多线程和:"+demo.numsum);

    }
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

CtrlZ1

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值