Executors.newSingleThreadExecutor的一些坑

2023-05-16

还是直接上源码吧

public static ExecutorService newSingleThreadExecutor() {
        return new FinalizableDelegatedExecutorService
            (new ThreadPoolExecutor(1, 1,
                                    0L, TimeUnit.MILLISECONDS,
                                    new LinkedBlockingQueue<Runnable>()));
    }

上面这段代码就是Executors.newSingleThreadExecutor方法得源码,因为FinalizableDelegatedExecutorService使用的是代理模式,所以接下来再看一下ThreadPoolExecutor的构造函数:

    public ThreadPoolExecutor(int corePoolSize,
                              int maximumPoolSize,
                              long keepAliveTime,
                              TimeUnit unit,
                              BlockingQueue<Runnable> workQueue,
                              ThreadFactory threadFactory,
                              RejectedExecutionHandler handler) {
        if (corePoolSize < 0 ||
            maximumPoolSize <= 0 ||
            maximumPoolSize < corePoolSize ||
            keepAliveTime < 0)
            throw new IllegalArgumentException();
        if (workQueue == null || threadFactory == null || handler == null)
            throw new NullPointerException();
        this.corePoolSize = corePoolSize;
        this.maximumPoolSize = maximumPoolSize;
        this.workQueue = workQueue;
        this.keepAliveTime = unit.toNanos(keepAliveTime);
        this.threadFactory = threadFactory;
        this.handler = handler;
    }
这里有两个参数需要注意以下:corePoolSize和maximumPoolSize。看一下这两个参数的说明:

    *
     * @param corePoolSize the number of threads to keep in the pool, even
     *        if they are idle, unless {@code allowCoreThreadTimeOut} is set
     * @param maximumPoolSize the maximum number of threads to allow in the
     *        pool
意思大概是说corePoolSize是线程池中的最大线程数量,而maxmumPoolSize意思是阻塞队列最大的阻塞线程数量,然后我们再回去看一下Executors.newSingleThreadService方法,给出的这两个参数都是1,那么问题来了,如果我想要搞一个只有一个运行线程的线程池时这个方法就不能满足我们的需求了,那么直接new一个ThreadPoolExecutor如:new ThreadPoolExecutor(1, 0, 0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<Runnable>())可不可以呢?答案是:不可以,因为在ThreadPoolExecutor的构造函数里第一个if语句就判断了,如果maximumPoolSize <= 0就会抛出一个异常。再回来看看,如果我们使用了JDK自带的newSingleThreadPool会发生什么情况:

1. 第一次submit一个线程,因为没有在运行的线程,所以该线程不会被提交到阻塞队列里,而是直接start运行。

2. 紧接着我们再submit一个线程,这次因为已经有一个线程在运行了,并且运行的线程数量等于corePoolSize所以,这个线程会被提交到阻塞队列。

3. 再submit第三个线程,这次就是饱和策略大显身手的时候了。

What,我原本是不想让第二个线程提交的,这样不就算是重复提交了吗?对,是重复提交。所以看来自带的JDK给的线程池是不能满足需求了。下面是ThreadPoolExecutor.execute方法的部分源码,可以解释上面的分析结果:

       int c = ctl.get();
        if (workerCountOf(c) < corePoolSize) {
            if (addWorker(command, true))
                return;
            c = ctl.get();
        }
        if (isRunning(c) && workQueue.offer(command)) {
            int recheck = ctl.get();
            if (! isRunning(recheck) && remove(command))
                reject(command);
            else if (workerCountOf(recheck) == 0)
                addWorker(null, false);
        }






本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Executors.newSingleThreadExecutor的一些坑 的相关文章

随机推荐

  • 头文件atlstr.h使用错误问题

    我的代码编译时出现如下错误 xff1a Error 33 fatal error LNK1120 1 unresolved externals Error 32 error LNK2001 unresolved external symbo
  • ubuntu编译服务器搭建

    我们现在开始做Android项目 xff0c 编译Android源码必不可少 但是Android编译需要Linux平台 xff08 一般都采用ubuntu xff09 xff0c 而且各种环境搭建繁杂 xff0c 编译时间长 xff0c 占
  • SWDL学习篇

    WSDL 学习篇 1 什么是WSDL WSDL 是网络服务描述语言 xff0c 使用xml 编写 xff0c 是xml 文档 xff0c 可规定服务的位置以及提供服务的操作和方法 2 WSDL 文档结构 1 lt portType gt 元
  • linux面试题

    1 在Linux系统中 以 文件 方式访问设备 2 Linux内核引导时 从文件 etc fstab 中读取要加载的文件系统 3 Linux文件系统中每个文件用 i节点 来标识 4 全部磁盘块由四个部分组成 分别为 引导块 专用块 i节点表
  • MySql学习笔记(一)MySql卸载和安装说明

    MySql卸载 开始 控制面板 程序和功能 MySQL server xx 卸载 删除 C Program Files x86 MySQL 文件 删除 C ProgramData MySQL 文件 xff08 隐藏目录 xff09 如果以上
  • MySql学习笔记(二)MySql配置文件和服务操作说明

    Mysql配置文件说明 MySQL MySQL ServerX X my ini mysqld 为服务端配置 xff0c 服务端端口号 port 61 3306 安装目录 basedir 61 34 C Program Files MySQ
  • MySql学习笔记(三)MySql常用命令说明

    一 数据库命令 1 1显示数据库命令 命令 xff1a mysql gt show databases 执行后 xff1a 43 43 Database 43 43 information schema mysql performance
  • ubuntu 使用dpkg手动安装deb包时发生循环依赖的解决办法

    将循环依赖的所有包放到同一个命令行里一起安装 xff0c 如 xff1a sudo dpkg i libnss3 nssdb 3 28 4 0ubuntu0 14 04 4 all deb libnss3 3 28 4 0ubuntu0 1
  • 什么是源端口和目的端口

    源端口就是指本地端口 目的端口就是远程端口 一个数据包 xff08 pocket xff09 被解封装成数据段 xff08 segment xff09 后就会涉及到 连接上层协议的端口问题 很多人都在源端口和目的端口这两个概念上犯迷糊 xf
  • ini文件

    关于ini 文件的存储于加载 xff0c 初次遇到 xff0c 刚接触ini 文件 xff0c 我想我该把它记下 xff0c 以后提醒自己要常用 参数 保存 xff1a 参数结构体 struct TextConfig int nVol 音量
  • MIUI9线刷包精简

    MIUI9线刷包精简 1 说明 xff1a 系统包一经修改 xff0c 将无法通过OTA升级 xff08 可能只是修改system分区的无法OTA升级 xff0c 一般精简都修改system分区 xff0c system分区未修改的能不能O
  • logback高级特性使用(三)

    本文转自 xff1a 点击打开链接 异步记录日志 注意 xff1a 该功能需要高版本才能支持 xff0c 如1 0 11 AsyncAppender xff0c 异步记录日志 工作原理 xff1a 当Logging Event进入Async
  • spring 官方下载地址(Spring Framework 3.2.x&Spring Framework 4.0.x)

    本文转自 xff1a 点击打开链接 SPRING官方网站改版后 xff0c 建议都是通过 Maven和Gradle 下载 xff0c 对不使用 Maven和Gradle 开发项目的 xff0c 下载就非常麻烦 xff0c 下给出Spring
  • ThreadLocal是否会引起内存溢出?

    本文参考 xff1a 点击打开链接 最近碰到一个使用ThreadLocal时因为未调用remove 而险些引起内存溢出的问题 xff0c 所以看了下ThreadLocal的源码 xff0c 结合线程池原理做一个简单的分析 xff0c 确认是
  • JS判断日期范围(日期范围应在一个月之内)

    本文转自 xff1a 点击打开链接 之前的一个项目的日期选择功能由单个日期 xff0c 修改为日期范围 xff0c 用到了日期范围的判断 xff0c 使用JS实现 xff0c 希望对需要的人有所帮助 代码如下 xff1a var start
  • python视频教程大全集下载啦

    本文转自 xff1a 点击打开链接 python3英文视频教程 全87集 http pan baidu com s 1dDnGBvV python从入门到精通视频 xff08 全60集 xff09 链接 xff1a http pan bai
  • 如何关闭ubuntu alt快捷键

    本文转自 xff1a 点击打开链接 有时候发现ubuntu的alt快捷键真是太烦人了 xff0c 动不动就能把搜索框呼唤出来 xff0c 尤其是我在ubuntu上装了win7虚拟机 xff0c 喜欢用qq的alt 43 s发送消息 xff0
  • ubuntu安装原生迅雷,让下载成为简单

    今天想到电影天堂下点电影 xff0c 发现TM全都是迅雷链接 xff0c 旋风链接什么的 无奈自带的BT下载器速度又慢 xff0c 又满足不了日常的一些文件下载 于是乎google了下 xff0c 哎呀 xff0c 有个mldonkey的电
  • Android 采用fastboot刷system.img boot.img recovery.img’

    手机正常启动后 xff0c 命令行模式下输入 adb reboot bootloader 该命令会自动进入fastboot模式 接着 xff1a fastboot devices 查看是否有设备 erase 擦除的意思 xff0c 你懂得
  • Executors.newSingleThreadExecutor的一些坑

    还是直接上源码吧 public static ExecutorService newSingleThreadExecutor return new FinalizableDelegatedExecutorService new Thread