Java多线程实现加法计算

采用多线程的方式实现从1到N的和

1.直接顺序计算

    public static void Sum(int N){
        long start1 = System.currentTimeMillis();
        long sum = 0;
        for(int i=1; i<=N; i++){
            sum += i;
        }
        long end1 = System.currentTimeMillis();
        System.out.println("串行计算耗时:" + (end1 - start1) + " ms");
        System.out.println("串行计算的结果:" + sum);
    }

    public static void main(String[] args) throws ExecutionException,         
                                       InterruptedException, BrokenBarrierException 
    {
        //实现多线程加法求和
        int N = 90000000;
        //mutilSum(arr, N, 2);
        Sum(N);
        //countDownLatchSum(N, 9);
        //cyclicBarrierSum2(N, 9);
    }

运行结果如下:

2.线程池和Callable

利用Callable接口可以在线程中返回结果,利用Future可以阻塞获取结果,利用线程池可以批量产生多个线程

    public static class SumThread implements Callable<Long>{

        private long start;
        private long end;

        public SumThread(long start, long end){
            this.start = start;
            this.end = end;
        }

        @Override
        public Long call() throws Exception {
            long sum  = 0L;
            for(long i = start; i<end; i++){
                sum += i;
            }
            return sum;
        }
    }

    //使用线程池+Callable接口
    public static void mutilSum(int N, int numThread) throws ExecutionException, 
                                                            InterruptedException {
        ExecutorService executor = Executors.newFixedThreadPool(numThread);
        long start1 = System.currentTimeMillis();
        List<Future<Long>> ans = new ArrayList<>();
        for(int i=0; i<numThread; i++){
            Future<Long> a = executor.submit(
                  new SumThread(i*N/numThread, (i+1)*N/numThread));
            ans.add(a);
        }
        long sum = 0;
        for (Future<Long> i : ans) {
            long tmp = i.get();
            System.out.println("线程 "+i +" 的结果是: "+tmp);
            sum += tmp;
        }
        //并行计算
        long end1 = System.currentTimeMillis();
        System.out.println("并行计算耗时:" + (end1 - start1) + " ms");
        System.out.println("并行计算的结果:" + sum);
    }

依次改变线程池的数量1,2,3,5,9,20,结果如下:

由测试可知,增加线程池得数量可以减少计算时间,然而当线程池数量过大时,计算性能会下降,这主要涉及到线程池的使用以及cpu核数与线程调度的关系,当线程数量过大时,会进行频繁得上下文切换,导致cpu不能充分进行计算。

3.CountDownLatch

 public static class SumCThread implements Runnable{

        private long start;
        private long end;
        private long[] result;
        private CountDownLatch cdl;
        private int num;

        public SumCThread(CountDownLatch cdl, long[] result, long start, long end,                                                                                                                         
                                                                         int num){
            this.result = result;
            this.start = start;
            this.end = end;
            this.cdl = cdl;
            this.num = num;
        }

        @Override
        public void run(){
            long sum = 0L;
            for(long i=start; i<end; i++){
                sum += i;
            }
            result[num] = sum;
            cdl.countDown();
        }
    }


    //每个线程结果怎么返回  线程如何等待最终求值
    //使用CountDownLatch
    public static void countDownLatchSum(int N, int numThread) throws 
                                                    InterruptedException {
        long start1 = System.currentTimeMillis();
        CountDownLatch cdl = new CountDownLatch(numThread);
        long[] result = new long[numThread];
        long sum = 0L;
        for(int i=0; i<numThread; i++){
            new Thread(
               new SumCThread(cdl, result,i*N/numThread, (i+1)*N/numThread, i))
            .start();
        }
        cdl.await();
        for(int i=0; i<numThread; i++){
            sum += result[i];
        }
        //并行计算
        long end1 = System.currentTimeMillis();
        System.out.println("并行计算耗时:" + (end1 - start1) + " ms");
        System.out.println("并行计算的结果:" + sum);
    }

依次改变线程池数量1,3,9

4.CyclicBarrier

使用CycleBarrier来进行线程同步,待所有线程计算完毕,在主线程计算中间数组之和,求出最后结果

    public static class SumCBThread implements Runnable{

        private long start;
        private long end;
        private long[] result;
        private CyclicBarrier cb;
        private int num;

        public SumCBThread(CyclicBarrier cb, long[] result, long start, long end, 
                                                                       int num){
            this.result = result;
            this.start = start;
            this.end = end;
            this.cb = cb;
            this.num = num;
        }

        @Override
        public void run(){
            long sum = 0L;
            for(long i=start; i<end; i++){
                sum += i;
            }
            result[num] = sum;
            try {
                cb.await();
            } catch (InterruptedException e) {
                e.printStackTrace();
            } catch (BrokenBarrierException e) {
                e.printStackTrace();
            }
        }
    }

    //使用同步屏障来实现
    public static void cyclicBarrierSum(int N, int numThread) throws 
                                   BrokenBarrierException, InterruptedException {
        long start1 = System.currentTimeMillis();
        CyclicBarrier cb = new CyclicBarrier(numThread+1);
        long[] result = new long[numThread];
        long sum = 0L;
        for(int i=0; i<numThread; i++){
            new Thread(
                new SumCBThread(cb, result,i*N/numThread, (i+1)*N/numThread, i))
            .start();
        }
        cb.await();
        for(int i=0; i<numThread; i++){
            sum += result[i];
        }
        //并行计算
        long end1 = System.currentTimeMillis();
        System.out.println("并行计算耗时:" + (end1 - start1) + " ms");
        System.out.println("并行计算的结果:" + sum);
    }

使用CycleBarrier构造器,传入线程同步时进行操作的Runnable接口方法

public static class SumCB implements Runnable{

        long[] result;

        public SumCB(long[] result){
            this.result = result;
        }

        @Override
        public void run() {
            long sum = 0L;
            for(int i=0; i<result.length; i++){
                sum += result[i];
            }
            System.out.println("并行计算的结果:" + sum);
        }
    }

    public static void cyclicBarrierSum2(int N, int numThread) throws 
                                   BrokenBarrierException, InterruptedException {
        long start1 = System.currentTimeMillis();
        long[] result = new long[numThread];
        CyclicBarrier cb = new CyclicBarrier(numThread, new SumCB(result));
        for(int i=0; i<numThread; i++){
            new Thread(
               new SumCBThread(cb, result,i*N/numThread, (i+1)*N/numThread, i))
            .start();
        }
        //并行计算
        long end1 = System.currentTimeMillis();
        System.out.println("并行计算耗时:" + (end1 - start1) + " ms");
    }

5.ForkJoin

利用ForkJoin框架来fork拆分,分段计算,然后执行join来合并最终结果

public class ForkJoinCalculate extends RecursiveTask<Long> {

    private long start;
    private long end;

    private static final long THRESHOLD = 10000;

    public ForkJoinCalculate(long start, long end){
        this.start = start;
        this.end = end;
    }

    @Override
    protected Long compute() {
        long length = end - start;
        if(length <= THRESHOLD){
            long sum = 0;
            for(long i=start; i<=end; i++){
                sum += i;
            }
            return sum;
        }else{
            long middle = (start + end) >> 1;
            ForkJoinCalculate left = new ForkJoinCalculate(start, middle);
            left.fork();
            ForkJoinCalculate right = new ForkJoinCalculate(middle+1, end);
            right.fork();
            return left.join() + right.join();
        }
    }

    public static void main(String[] args) {
        Instant start = Instant.now();
        ForkJoinPool pool = new ForkJoinPool();
        ForkJoinTask<Long> task = new ForkJoinCalculate(1, 100000L);
        Long sum = pool.invoke(task);
        System.out.println(sum);
        Instant end = Instant.now();
        System.out.println(Duration.between(start, end).getNano());
    }
}

 

  • 3
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值