多线程与单线程执行的对比

对比技术点:
单线程:普通循环
多线程框架:CompletableFuture
多线程框架;ForkJoin
50次对比实验

 

源码:

 

package com.example.demo;

import org.apache.commons.lang3.time.StopWatch;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ForkJoinPool;
import java.util.concurrent.RecursiveTask;
import java.util.concurrent.atomic.AtomicInteger;

public class CacheAndIndexExample {


    public static void main(String[] args) {
        // 创建多个CompletableFuture任务
        for (int n = 0; n < 50; n++) {


        try {
            // 使用allOf方法等待所有任务完成
            StopWatch stopWatch = StopWatch.createStarted();
            CompletableFuture<Integer> future1 = CompletableFuture.supplyAsync(() -> task1());
            CompletableFuture<Integer> future2 = CompletableFuture.supplyAsync(() -> task2());
            CompletableFuture<Integer> future3 = CompletableFuture.supplyAsync(() -> task3());


            CompletableFuture.allOf(future1, future2, future3).join();
            // 获取每个任务的结果
            int result1 = future1.get();
            int result2 = future2.get();
            int result3 = future3.get();
            System.out.println("11111111111111时间:" + stopWatch.getTime());
            System.out.println("11111111111111结果:"+(result1+result2+result3));

            AtomicInteger atomicInteger = new AtomicInteger(0);
            StopWatch stopWatch0 = StopWatch.createStarted();
            for (int i = 0; i < 600000; i++) {
                if (get(i)) {
                    atomicInteger.getAndAdd(1);
                }
            }
            int i = atomicInteger.get();
            System.out.println("2222222222时间:" + stopWatch0.getTime());
            System.out.println("2222222222结果:"+i);
//            // 处理最终的结果
            ArrayList<Integer> arrayList = new ArrayList<>();
            for (int j = 0; j < 600000; j++) {
                arrayList.add(j);
            }
            ForkJoinPool forkJoinPool = new ForkJoinPool();
            StopWatch stopWatch1 = StopWatch.createStarted();
            MyTask task = new MyTask(arrayList);
            Integer invoke = forkJoinPool.invoke(task);
            System.out.println("333333333333时间:" + stopWatch1.getTime());
            System.out.println("33333333333结果:" + invoke);
        } catch (InterruptedException | ExecutionException e) {
            e.printStackTrace();
        }
        }
    }

    private static int task1() {
        AtomicInteger atomicInteger = new AtomicInteger(0);
        for (int i = 0; i < 200000; i++) {
            if (get(i)) {
                atomicInteger.getAndAdd(1);
            }
        }
        return atomicInteger.get();
    }

    private static Integer task2() {
        AtomicInteger atomicInteger = new AtomicInteger(0);
        for (int i = 0; i < 200000; i++) {
            if (get(i)) {
                atomicInteger.getAndAdd(1);
            }
        }
        return atomicInteger.get();
    }

    private static Integer task3() {
        AtomicInteger atomicInteger = new AtomicInteger(0);
        for (int i = 0; i < 200000; i++) {
            if (get(i)) {
                atomicInteger.getAndAdd(1);
            }
        }
        return atomicInteger.get();
    }

    private static boolean get(Integer i) {
        if (i % 2 == 0) {
            return true;
        }
        return false;
    }


    public static class MyTask extends RecursiveTask<Integer> {
        private static final int THRESHOLD = 100000;
        private List<Integer> start;


        public MyTask(List<Integer> start) {
            this.start = start;
        }

        @Override
        protected Integer compute() {
            boolean compute = start.size() <= THRESHOLD;
            if (compute) {
                // 执行任务的逻辑
                int sum = 0;
                int size = start.size();
                for (int i = 0; i < size; i++) {
                    if (get(i)) {
                        sum++;
                    }
                }
                return sum;
            } else {
                int mid = start.size() / 2;
                List<Integer> leftSubList = start.subList(0, mid);
                List<Integer> rightSubList = start.subList(mid, start.size());
                MyTask leftTask = new MyTask(leftSubList);
                MyTask rightTask = new MyTask(rightSubList);
                leftTask.fork();
                int rightResult = rightTask.compute();
                int leftResult = leftTask.join();
                return leftResult + rightResult;
            }
        }

        private boolean get(Integer i) {
            if (i % 2 == 0) {
                return true;
            }
            return false;
        }

//        private List<List<Integer>> splitList(List<Integer> bigList, int batchSize) {
//            List<List<Integer>> smallLists = new ArrayList<>();
//            int size = bigList.size();
//            for (int i = 0; i < size; i += batchSize) {
//                int fromIndex = i;
//                int toIndex = Math.min(i + batchSize, size);
//                List<Integer> smallList = bigList.subList(fromIndex, toIndex);
//                smallLists.add(smallList);
//            }
//            return smallLists;
//        }
    }
}

 

结果:

 

11111111111111时间:21    2222222222时间:16   333333333333时间:22
11111111111111时间:18    2222222222时间:5    333333333333时间:28
11111111111111时间:9      2222222222时间:11  333333333333时间:14
11111111111111时间:1       2222222222时间:2   333333333333时间:3
11111111111111时间:26     2222222222时间:5   333333333333时间:3
11111111111111时间:2     2222222222时间:5    333333333333时间:2
11111111111111时间:1     2222222222时间:11   333333333333时间:1
11111111111111时间:2    2222222222时间:27    333333333333时间:2
11111111111111时间:2   2222222222时间:2    333333333333时间:2
11111111111111时间:4   2222222222时间:33   333333333333时间:2
11111111111111时间:3   2222222222时间:3   333333333333时间:2
11111111111111时间:3  2222222222时间:3   333333333333时间:3
11111111111111时间:2   2222222222时间:5   333333333333时间:2
11111111111111时间:2   2222222222时间:5   333333333333时间:2
11111111111111时间:2   2222222222时间:42  333333333333时间:2
11111111111111时间:1   2222222222时间:2  333333333333时间:2
11111111111111时间:1   2222222222时间:2   333333333333时间:2
11111111111111时间:2   2222222222时间:50  333333333333时间:2
11111111111111时间:1   2222222222时间:2   333333333333时间:2
11111111111111时间:1   2222222222时间:2   333333333333时间:1
11111111111111时间:1   2222222222时间:3   333333333333时间:60
11111111111111时间:1   2222222222时间:2   333333333333时间:2
11111111111111时间:1   2222222222时间:2   333333333333时间:2
11111111111111时间:1   2222222222时间:2   333333333333时间:2
11111111111111时间:1   2222222222时间:2   333333333333时间:90
11111111111111时间:2   2222222222时间:5   333333333333时间:3
11111111111111时间:2   2222222222时间:5   333333333333时间:3
11111111111111时间:2   2222222222时间:5   333333333333时间:3
11111111111111时间:2   2222222222时间:6   333333333333时间:3
11111111111111时间:2
2222222222时间:68
333333333333时间:2
11111111111111时间:1
2222222222时间:2
333333333333时间:2
11111111111111时间:1
2222222222时间:2
333333333333时间:2
11111111111111时间:1
2222222222时间:2
333333333333时间:1
11111111111111时间:0
2222222222时间:2
333333333333时间:2
11111111111111时间:2
2222222222时间:5
333333333333时间:2
11111111111111时间:1
2222222222时间:2
333333333333时间:2
11111111111111时间:1
2222222222时间:2
333333333333时间:1
11111111111111时间:1
2222222222时间:2
333333333333时间:5
11111111111111时间:1
2222222222时间:2
333333333333时间:2
11111111111111时间:1
2222222222时间:2
333333333333时间:2
11111111111111时间:1
2222222222时间:2
333333333333时间:4
11111111111111时间:1
2222222222时间:3
333333333333时间:2
11111111111111时间:1
2222222222时间:2
333333333333时间:1
11111111111111时间:1
2222222222时间:2
333333333333时间:1
11111111111111时间:1
2222222222时间:2
333333333333时间:2
11111111111111时间:0
2222222222时间:2
333333333333时间:2
11111111111111时间:1
2222222222时间:2
333333333333时间:2
11111111111111时间:111
2222222222时间:6
333333333333时间:3
11111111111111时间:2
2222222222时间:7
333333333333时间:3
11111111111111时间:2
2222222222时间:6
333333333333时间:3

 

总结多核cpu情况下总体上使用多线程并行执行结果大概率会好很多,
如果机器cpu被打满,即便是多线程也抢不到资源去执行。极个别情况下多线程等待cpu切换耗费时间,比单线程消耗时间还长

 

posted @ 2023-08-30 23:37  余生请多指教ANT  阅读(22)  评论(0编辑  收藏  举报