FixedThreadPool vs CachedThreadPool

以前写了一篇文章关于四种线程池的解析。
可是对于FixedThreadPool与CachedThreadPool适用的场景其实仍是比较模糊难以界定的。因此笔者今天经过设计大任务并发和小任务并发来验证FixedThreadPool与CachedThreadPool的适用场景。

首先我设计了一个任务基类,它经过计算圆周率来模拟cpu的密集计算、经过写日志到本地文件来模拟IO。
这两个方法都经过参数n来调整任务的大小规模。html

public class Task {
    
    /**
     * 经过计算圆周率模拟cpu计算
     * 经过公式 π=4*(1-1/3+1/5-1/7+1/9-1/11+....)
     *
     * @return
     */
    public static double calculatePI(long n) {

        double item = 0.0;
        double sum = 0;
        int flag = -1;

        for (int i = 0; i <= n; i++) {
            flag *= -1;
            item = flag * 1.0 / (2 * i + 1);
            sum += item;
        }

        return sum * 4;

    }
    
    /**
     * 经过写日志模拟IO操做
     * @param n
     */
    public static void writeIO(int n) {

        try {

            Date date = new Date();

            SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd-HH-mm-ss-SSS");

            String fileName = Thread.currentThread().getName() + "-" + format.format(date) + ".log";

            FileOutputStream os = new FileOutputStream("C:\\Users\\valarchie\\Desktop\\logs\\" + fileName);

            for (int i = 0; i < n; i++) {
                os.write(("写入日志" + i + "次").getBytes());
            }

        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }

    }


}

在笔者的设计当中大任务的规模是小任务的10倍,具体请看代码:多线程

大任务:并发

public class BigTask extends Task implements Runnable {

    private CountDownLatch latch;

    public BigTask(CountDownLatch latch) {
        this.latch = latch;
    }
    
    public static double calculatePI() {
        return calculatePI(100000000);
    }
    
    public static void writeIO() {
        writeIO(100);
    }

    @Override
    public void run() {
        calculatePI();
        writeIO();
        latch.countDown();
    }
    
}

小任务:ide

public class SmallTask extends Task implements Runnable  {
    
    private CountDownLatch latch;

    public SmallTask(CountDownLatch latch) {
        this.latch = latch;
    }

    public static double calculatePI() {
        return calculatePI(10000000);
    }


    public static void writeIO() {
        writeIO(10);
    }
    
    @Override
    public void run() {
        calculatePI();
        writeIO();
        latch.countDown();
    }
}

经过测试咱们得出一个小任务的运行时间大概在86ms左右。一个大任务的运行时间大概在575ms左右。
接下来咱们分别测试100个大任务和100个小任务分别在单线程、FixedThreadPool、CachedThreadPool三种状况下的运行时间(个人笔记本是4核的,通过简单测试FixedThreadPool在16线程数的状况下性能最优良)。性能

咱们使用CountDownLatch的计算多线程的运行时间,如下是多线程的测试代码模板:测试

public static void main(String[] args) {

        int taskCount = 100;

        CountDownLatch latch = new CountDownLatch(taskCount);

        ExecutorService executorService = Executors.newFixedThreadPool(16);

        long t1 = System.currentTimeMillis();

        for (int i = 0; i < taskCount; i++) {
            executorService.submit(new SmallTask(latch));
        }

        try {
            latch.await();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        long t2 = System.currentTimeMillis();
        // 得出多线程的运行时间
        System.out.println(t2 - t1);
        executorService.shutdown();

    }
任务模型*100 单线程 FixedThreadPool CachedThreadPool
大任务 45067ms 6613ms 6224ms
小任务 4754ms 722ms 726ms

经过统计发现多线程的性能比单线程的性能优异不少,可是其实FixedThreadPool和CachedThreadPool的性能差别是差很少相等的并无比较大差异。this

为了更严谨一点,咱们控制任务方法的规模和任务数量的规模再进行一次测试线程

任务模型*100 FixedThreadPool CachedThreadPool
大任务方法规模*10 78738ms 79669ms
大任务数量规模*10 73654ms 69343ms

结果发现其实性能上仍是没有差别。

笔者通过验证得出的结论是两种线程池其实在性能上没有很是大差异,可是FixedThreadPool能够控制线程的并发数量,而CachedThreadPool不能控制线程的并发数量。若是线程数量爆发增加的话对系统会带来危害。我的认为使用FixedThreadPool会更好。设计

笔者认知水平有限,若有错误恳请评论区指正。

转自个人我的博客 vc2x.com日志

相关文章
相关标签/搜索