使用线程池测试cpu的并发计算能力

接到一个需求是测试一下cpu并发计算能力,针对int和float求和单位时间能执行几次的问题。可能是服务器选型用到的参数。

开始使用的是fork-join,但是发现fork-join每次得到的结果值波动很明显不稳定(可能和fork-join的实现有关系,抽空研究一下),所以用了线程池的思路来实现

ps:

当然你可以把这篇文章作为线程池和Callable结合并发计算的一个demo来看

代码如下:

package com.company;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.FutureTask;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

/**
 * @author nf
 * 多线程累加求和
 * 
 */
public class CpuTestByThreadPool{
    private ThreadPoolExecutor pool = null;
    public void init(int poolCount) {
        pool = new ThreadPoolExecutor(
                poolCount,
                poolCount*2,
                30,
                TimeUnit.MINUTES,
                new ArrayBlockingQueue<Runnable>(10));
    }
    public void destory() {
        if(pool != null) {
            pool.shutdownNow();
        }
    }
    private class Sum implements Callable<Integer>{
        private int subMin;
        private int subMax;
        private int[] arr;
        public Sum(int subMin,int subMax,int[] arr){
            this.subMin = subMin;
            this.subMax = subMax;
            this.arr = arr;
        }
        @Override
        public Integer call() throws Exception {
            int sum = 0;
            for(int i = subMin;i <= subMax;i++){
                sum += arr[i];
            }
            return sum;
        }
    }

    /**
     * 求和范围是 min ~ max
     * @param min
     * @param max
     * @param threadNum
     * @return
     */
    public Integer getSum(int min, int max,int[] arr, int threadNum){
        int subMin;
        int subMax;
        List<FutureTask<Integer>> taskList = new ArrayList<>();
        int sumCounts = max - min;
        int subCounts = sumCounts/threadNum;
        int remainder = sumCounts%threadNum;
        int mark = min;
        for(int i = 0;i<threadNum;i++){
            subMin = mark;
            if(remainder!=0&&remainder>i){
                subMax = subMin + subCounts;
            }else{
                subMax = mark + subCounts - 1;
            }
            mark = subMax + 1;
            FutureTask<Integer> task = new FutureTask<Integer>(new Sum(subMin,subMax,arr));
            taskList.add(task);
            pool.execute(new Thread(task));
        }
        int sum = taskListSum(taskList);
        return sum;
    }
    
    private Integer taskListSum(List<FutureTask<Integer>> taskList){
        int sum = 0;
        for(FutureTask<Integer> task : taskList){
            try {
                sum += task.get();
            } catch (InterruptedException e) {
                e.printStackTrace();
            } catch (ExecutionException e) {
                e.printStackTrace();
            }
        }
        return sum;
    }
    
    private class SumFloat implements Callable<Float>{
        private int subMin;
        private int subMax;
        private Float[] arr;
        public SumFloat(int subMin,int subMax,Float[] arr){
            this.subMin = subMin;
            this.subMax = subMax;
            this.arr = arr;
        }
        @Override
        public Float call() throws Exception {
            Float sum = 0f;
            for(int i = subMin;i <= subMax;i++){
                sum += arr[i];
            }
            return sum;
        }
    }

    /**
     * 求和范围是 min ~ max
     * @param min
     * @param max
     * @param threadNum
     * @return
     */
    public Float getSumFloat(int min, int max,Float[] arr, int threadNum){
        int subMin;
        int subMax;
        List<FutureTask<Float>> taskList = new ArrayList<>();
        int sumCounts = max - min;
        int subCounts = sumCounts/threadNum;
        int remainder = sumCounts%threadNum;
        int mark = min;
        for(int i = 0;i<threadNum;i++){
            subMin = mark;
            if(remainder!=0&&remainder>i){
                subMax = subMin + subCounts;
            }else{
                subMax = mark + subCounts - 1;
            }
            mark = subMax + 1;
            FutureTask<Float> task = new FutureTask<Float>(new SumFloat(subMin,subMax,arr));
            taskList.add(task);
            pool.execute(new Thread(task));
        }
        Float sum = taskListSumFloat(taskList);
        return sum;
    }
    
    private Float taskListSumFloat(List<FutureTask<Float>> taskList){
        Float sum = 0f;
        for(FutureTask<Float> task : taskList){
            try {
                sum += task.get();
            } catch (InterruptedException e) {
                e.printStackTrace();
            } catch (ExecutionException e) {
                e.printStackTrace();
            }
        }
        return sum;
    }

    /**
     * @param args
     * 测试
     * @throws InterruptedException 
     */
    public static void main(String[] args) throws InterruptedException{
        //修改这三个参数
        final int arrSize = 2800000,sleeptime=10000;
        final int poolCount = 10;
        int[] arr = new int[arrSize];
        for (int i = 0; i < arrSize; i++) {
            arr[i] = i + 1;
        }

        Float[] arrFloat = new Float[arrSize];
        for (int i = 0; i < arrSize; i++) {
            arrFloat[i] = i + (((float)i) / 3f);
        }
        CpuTestByThreadPool sumCalculator = new CpuTestByThreadPool();
        
        sumCalculator.init(poolCount);
        long startTime = 0L;
        long endTime = 0L;
        long countL=0L,countF=0L;
        startTime = System.nanoTime();
        while ((endTime-startTime)<10000000000L) {//10秒
            sumCalculator.getSum(0, arrSize,arr, poolCount);
            endTime = System.nanoTime();
            countL++;
        }
        System.out.println(countL);
        Thread.sleep(sleeptime);
        endTime = 0L;
        startTime = System.nanoTime();
        while ((endTime-startTime)<10000000000L) {
            sumCalculator.getSumFloat(0, arrSize, arrFloat, poolCount);
            endTime = System.nanoTime();
            countF++;
        }
        System.out.println(countF);
        sumCalculator.destory();
        
        System.out.println("TPCC=  " + (countL+countF)/2 + "tpmC");
    }

}
可以通过修改arrSize = 2800000;poolCount = 10;这两个参数匹配自己的机器(让运行时cpu内核占满就行了)

posted @ 2019-01-29 17:19  一腿狗毛  阅读(893)  评论(0编辑  收藏  举报