FixedThreadPool vs CachedThreadPool

本贴最后更新于 1680 天前,其中的信息可能已经时过境迁

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

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

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();
    }
    
}

小任务:

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 的性能差异是差不多相等的并没有比较大差别。

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

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

结果发现其实性能上还是没有差异。

笔者经过验证得出的结论是两种线程池其实在性能上没有非常大差别,但是 FixedThreadPool 可以控制线程的并发数量,而 CachedThreadPool 不能控制线程的并发数量。如果线程数量爆发增长的话对系统会带来危害。个人认为使用 FixedThreadPool 会更好。

笔者认知水平有限,如有错误恳请评论区指正。
  • 线程
    120 引用 • 111 回帖 • 3 关注

相关帖子

欢迎来到这里!

我们正在构建一个小众社区,大家在这里相互信任,以平等 • 自由 • 奔放的价值观进行分享交流。最终,希望大家能够找到与自己志同道合的伙伴,共同成长。

注册 关于
请输入回帖内容 ...

推荐标签 标签

  • 学习

    “梦想从学习开始,事业从实践起步” —— 习近平

    161 引用 • 473 回帖
  • 链书

    链书(Chainbook)是 B3log 开源社区提供的区块链纸质书交易平台,通过 B3T 实现共享激励与价值链。可将你的闲置书籍上架到链书,我们共同构建这个全新的交易平台,让闲置书籍继续发挥它的价值。

    链书社

    链书目前已经下线,也许以后还有计划重制上线。

    14 引用 • 257 回帖 • 1 关注
  • Flutter

    Flutter 是谷歌的移动 UI 框架,可以快速在 iOS 和 Android 上构建高质量的原生用户界面。 Flutter 可以与现有的代码一起工作,它正在被越来越多的开发者和组织使用,并且 Flutter 是完全免费、开源的。

    39 引用 • 92 回帖 • 8 关注
  • 开源中国

    开源中国是目前中国最大的开源技术社区。传播开源的理念,推广开源项目,为 IT 开发者提供了一个发现、使用、并交流开源技术的平台。目前开源中国社区已收录超过两万款开源软件。

    7 引用 • 86 回帖 • 1 关注
  • GAE

    Google App Engine(GAE)是 Google 管理的数据中心中用于 WEB 应用程序的开发和托管的平台。2008 年 4 月 发布第一个测试版本。目前支持 Python、Java 和 Go 开发部署。全球已有数十万的开发者在其上开发了众多的应用。

    14 引用 • 42 回帖 • 683 关注
  • 知乎

    知乎是网络问答社区,连接各行各业的用户。用户分享着彼此的知识、经验和见解,为中文互联网源源不断地提供多种多样的信息。

    10 引用 • 66 回帖
  • MongoDB

    MongoDB(来自于英文单词“Humongous”,中文含义为“庞大”)是一个基于分布式文件存储的数据库,由 C++ 语言编写。旨在为应用提供可扩展的高性能数据存储解决方案。MongoDB 是一个介于关系数据库和非关系数据库之间的产品,是非关系数据库当中功能最丰富,最像关系数据库的。它支持的数据结构非常松散,是类似 JSON 的 BSON 格式,因此可以存储比较复杂的数据类型。

    90 引用 • 59 回帖 • 2 关注
  • GitBook

    GitBook 使您的团队可以轻松编写和维护高质量的文档。 分享知识,提高团队的工作效率,让用户满意。

    3 引用 • 8 回帖
  • 大数据

    大数据(big data)是指无法在一定时间范围内用常规软件工具进行捕捉、管理和处理的数据集合,是需要新处理模式才能具有更强的决策力、洞察发现力和流程优化能力的海量、高增长率和多样化的信息资产。

    89 引用 • 113 回帖
  • 单点登录

    单点登录(Single Sign On)是目前比较流行的企业业务整合的解决方案之一。SSO 的定义是在多个应用系统中,用户只需要登录一次就可以访问所有相互信任的应用系统。

    9 引用 • 25 回帖 • 3 关注
  • flomo

    flomo 是新一代 「卡片笔记」 ,专注在碎片化时代,促进你的记录,帮你积累更多知识资产。

    3 引用 • 80 回帖 • 1 关注
  • 心情

    心是产生任何想法的源泉,心本体会陷入到对自己本体不能理解的状态中,因为心能产生任何想法,不能分出对错,不能分出自己。

    59 引用 • 369 回帖 • 2 关注
  • 微软

    微软是一家美国跨国科技公司,也是世界 PC 软件开发的先导,由比尔·盖茨与保罗·艾伦创办于 1975 年,公司总部设立在华盛顿州的雷德蒙德(Redmond,邻近西雅图)。以研发、制造、授权和提供广泛的电脑软件服务业务为主。

    8 引用 • 44 回帖
  • BND

    BND(Baidu Netdisk Downloader)是一款图形界面的百度网盘不限速下载器,支持 Windows、Linux 和 Mac,详细介绍请看这里

    107 引用 • 1281 回帖 • 20 关注
  • LaTeX

    LaTeX(音译“拉泰赫”)是一种基于 ΤΕΧ 的排版系统,由美国计算机学家莱斯利·兰伯特(Leslie Lamport)在 20 世纪 80 年代初期开发,利用这种格式,即使使用者没有排版和程序设计的知识也可以充分发挥由 TeX 所提供的强大功能,能在几天,甚至几小时内生成很多具有书籍质量的印刷品。对于生成复杂表格和数学公式,这一点表现得尤为突出。因此它非常适用于生成高印刷质量的科技和数学类文档。

    9 引用 • 32 回帖 • 168 关注
  • FFmpeg

    FFmpeg 是一套可以用来记录、转换数字音频、视频,并能将其转化为流的开源计算机程序。

    22 引用 • 31 回帖 • 2 关注
  • SMTP

    SMTP(Simple Mail Transfer Protocol)即简单邮件传输协议,它是一组用于由源地址到目的地址传送邮件的规则,由它来控制信件的中转方式。SMTP 协议属于 TCP/IP 协议簇,它帮助每台计算机在发送或中转信件时找到下一个目的地。

    4 引用 • 18 回帖 • 589 关注
  • danl
    63 关注
  • 招聘

    哪里都缺人,哪里都不缺人。

    189 引用 • 1056 回帖 • 1 关注
  • Flume

    Flume 是一套分布式的、可靠的,可用于有效地收集、聚合和搬运大量日志数据的服务架构。

    9 引用 • 6 回帖 • 595 关注
  • 友情链接

    确认过眼神后的灵魂连接,站在链在!

    24 引用 • 373 回帖 • 2 关注
  • frp

    frp 是一个可用于内网穿透的高性能的反向代理应用,支持 TCP、UDP、 HTTP 和 HTTPS 协议。

    15 引用 • 7 回帖 • 9 关注
  • ZeroNet

    ZeroNet 是一个基于比特币加密技术和 BT 网络技术的去中心化的、开放开源的网络和交流系统。

    1 引用 • 21 回帖 • 591 关注
  • Pipe

    Pipe 是一款小而美的开源博客平台。Pipe 有着非常活跃的社区,可将文章作为帖子推送到社区,来自社区的回帖将作为博客评论进行联动(具体细节请浏览 B3log 构思 - 分布式社区网络)。

    这是一种全新的网络社区体验,让热爱记录和分享的你不再感到孤单!

    131 引用 • 1114 回帖 • 152 关注
  • Python

    Python 是一种面向对象、直译式电脑编程语言,具有近二十年的发展历史,成熟且稳定。它包含了一组完善而且容易理解的标准库,能够轻松完成很多常见的任务。它的语法简捷和清晰,尽量使用无异义的英语单词,与其它大多数程序设计语言使用大括号不一样,它使用缩进来定义语句块。

    536 引用 • 672 回帖
  • C

    C 语言是一门通用计算机编程语言,应用广泛。C 语言的设计目标是提供一种能以简易的方式编译、处理低级存储器、产生少量的机器码以及不需要任何运行环境支持便能运行的编程语言。

    83 引用 • 165 回帖 • 45 关注
  • 游戏

    沉迷游戏伤身,强撸灰飞烟灭。

    169 引用 • 799 回帖 • 1 关注