在jdk中为我们提供了三种创建线程池的方式,但是在阿里的编码规范里面都是明确禁止使用这三种api去创建线程池,推荐我们去自定义线程池。为什么?

要回答为什么,我们需要明白创建线程池时,各参数的作用:

首先我们来看一下jdk提供的创建线程池的三个api:

1. newFixedThreadPool    创建固定数量线程的线程池。

2. newSingleThreadExecutor   创建单线程的线程池

3. newCachedThreadPool 创建一个带有缓存的线程池

发现这几种创建线程池的api,实质上都是依赖于ThreadPoolExecutor类来创建线程池。

那我们来看一下ThreadPoolExecutor 创建线程池时需要的参数,以及其作用。

创建一个线程池,需要7个参数。

1. corePoolSize: 线程池的核心线程数量。初始是不创建线程的。当有任务提交到线程池时,判定如果已经创建的线程数量小于核心数量,且没有空闲线程时,则会新建一个线程去执行新提交的任务。如果已经达到核心线程数量, 则会加入到阻塞队列中。

2.maximumPoolSize: 线程池的最大容量。当线程池的阻塞队列放满了, 并且线程数量还未达到线程池的最大线程数量, 则会创建新的线程,直到达到最大值

3.keepAliveTime   当阻塞队列里面的任务被执行完了, 且有空闲线程时,指定大于核心线程池数量的部分空闲线程的存活时间, 毕竟线程也是需要消耗资源的,及时回收很有必要。当线程空闲的时间超过这个时间后,会回收掉一部分空闲线程,使其线程池中的线程数量不大于核心线程的数量

4.unit  和keepAliveTIme 配套使用,上面指定了时间的数值,但是没有指定时间的单位(时,分,秒等), 这里需要指定时间的单位

5.workQueue  阻塞队列,当没有空闲线程时,多余的任务缓存的地方。

6.threadFactory 线程工厂,用来创建线程时,设定线程的一些参数。通常我们为了后续查看日志方便,可以通过这个来指定我们自定义的线程池的线程名称

7.handler  当线程数量达到最大值时,且阻塞队列慢了, 后续在提交任务时,没有地方可以接受继续的提交的任务。这种情况下的一个拒绝策略。

拒绝策略jdK,提供了四种:

// 由提交任务的线程执行任务
public static class CallerRunsPolicy implements RejectedExecutionHandler { public CallerRunsPolicy() { } public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {
if (!e.isShutdown()) {
r.run();
}
}
}

// 不在接收新的任务,直接抛出异常
public static class AbortPolicy implements RejectedExecutionHandler { public AbortPolicy() { } public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {
throw new RejectedExecutionException("Task " + r.toString() +
" rejected from " +
e.toString());
}
} // 不接收也不抛出异常,空实现,忽略该任务
public static class DiscardPolicy implements RejectedExecutionHandler { public DiscardPolicy() { } public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {
}
} // 抛弃最老的任务,从阻塞队列中移除最早提交的任务,然后将该任务加入。
public static class DiscardOldestPolicy implements RejectedExecutionHandler { public DiscardOldestPolicy() { } public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {
if (!e.isShutdown()) {
e.getQueue().poll();
e.execute(r);
}
}
}

讲解完了创建线池时,各参数的作用,那么我们现在再反过来看为什么不让使用jdk提供的apI来创建线程池,而是需要我们自定义线程池。

newFixedThreadPool ,newSingleThreadExecutor    这两种api 使用的阻塞队列都是无界队列,也就是无论有多少个任务来,我们都接收。我们的内存是有限的,阻塞队列里面存储的任务是越多,也就意味着占用的内存越多,这样会导致占用大量的内存,容易引起OOM

newCachedThreadPool  而这个api 的阻塞队列容量为0,最大线程数量为Integer 的最大值。每当有一个任务提交时,阻塞队列存储不了,就会新开启一个线程,当任务比较多,则会创建大量的线程, 引起OOM.

这就是为什么我们在使用线程池时一定要自定义线程池的原因了。

JDK中线程池参详细解析的更多相关文章

  1. 沉淀再出发:java中线程池解析

    沉淀再出发:java中线程池解析 一.前言 在多线程执行的环境之中,如果线程执行的时间短但是启动的线程又非常多,线程运转的时间基本上浪费在了创建和销毁上面,因此有没有一种方式能够让一个线程执行完自己的 ...

  2. Java并发编程中线程池源码分析及使用

    当Java处理高并发的时候,线程数量特别的多的时候,而且每个线程都是执行很短的时间就结束了,频繁创建线程和销毁线程需要占用很多系统的资源和时间,会降低系统的工作效率. 参考http://www.cnb ...

  3. 多线程(七)JDK原生线程池

    如同数据库连接一样,线程的创建.切换和销毁同样会耗费大量的系统资源.为了复用创建好的线程,减少频繁创建线程的次数,提高线程利用率可以引用线程池技术.使用线程池的优势有如下几点:        1.保持 ...

  4. [转] 引用 Java自带的线程池ThreadPoolExecutor详细介绍说明和实例应用

    PS: Spring ThreadPoolTaskExecutor vs Java Executorservice cachedthreadpool 引用 [轰隆隆] 的 Java自带的线程池Thre ...

  5. Java 线程池(ThreadPoolExecutor)原理解析

    在我们的开发中“池”的概念并不罕见,有数据库连接池.线程池.对象池.常量池等等.下面我们主要针对线程池来一步一步揭开线程池的面纱. 有关java线程技术文章还可以推荐阅读:<关于java多线程w ...

  6. Java中线程池,你真的会用吗?

    在<深入源码分析Java线程池的实现原理>这篇文章中,我们介绍过了Java中线程池的常见用法以及基本原理. 在文中有这样一段描述: 可以通过Executors静态工厂构建线程池,但一般不建 ...

  7. Java中线程池,你真的会用吗?ExecutorService ThreadPoolExcutor

    原文:https://www.hollischuang.com/archives/2888 在<深入源码分析Java线程池的实现原理>这篇文章中,我们介绍过了Java中线程池的常见用法以及 ...

  8. Java中java.util.concurrent包下的4中线程池代码示例

    先来看下ThreadPool的类结构 其中红色框住的是常用的接口和类(图片来自:https://blog.csdn.net/panweiwei1994/article/details/78617117 ...

  9. Java 中线程池的 7 种创建方式!

    在 Java 语言中,并发编程都是通过创建线程池来实现的,而线程池的创建方式也有很多种,每种线程池的创建方式都对应了不同的使用场景,总体来说线程池的创建可以分为以下两类: 通过 ThreadPoolE ...

随机推荐

  1. 【Linux_Shell 脚本编程学习笔记一、条件表达式】

    条件表达式返回的结果都为布尔型 真为1,假为0 条件测试的表达式 [expression] 比较符 整数比较 -eq:比较两个整数是否相等,$A -eq $B -ne:测试两个整数是否不等,不等则为真 ...

  2. .net和JAVA面向对象,继承有趣的细节

    原型是同事间讨论的一道面试题.估计这题秒杀了不少人,LZ也被秒了. 但这个题里隐藏了一个很有趣的细节,这个细节不说清楚,不少人会其实死的冤枉. 这是C#的代码. class Program { sta ...

  3. 在中国实现自我价值的英国研究员——微软亚洲研究院英国籍研究员Darren的7年之路

    "我和妻子在这儿已经待了7年了,这里的一切都很棒,无论是微软亚洲研究院还是北京."Darren笑着说,似乎他和中国,和北京,和研究院一直停留在"蜜月期",并未曾 ...

  4. 分布式ID生成策略 · fossi

    分布式环境下如何保证ID的不重复呢?一般我们可能会想到用UUID来实现嘛.但是UUID一般可以获取当前时间的毫秒数再加点随机数,但是在高并发下仍然可能重复.最重要的是,如果我要用这种UUID来生成分表 ...

  5. 我们为什么不愿意相信AI?

    人工智能--即AI已经变得越来越聪明,甚至能够预测未来.比如警察可以用AI来提前预判出犯罪的时间或地点,医生可以用AI预测病人最有可能心脏病发作或是中风.甚至研究人员还试图为AI添加上更多的想象力,因 ...

  6. 从高知社区知乎变故事会,看论坛IP的夹缝生存

    ​​ ​ ​ "海贼-王路飞"疯狂饰演多个角色答题的事件,最终以其被封杀为结果:知乎官方账号发表<知乎小管家工作笔记:我们封禁了几个伪造身份的帐号>,内容为公布了新一批 ...

  7. 记录R的一些黑魔法

    通路富集结果可视化 12345678 pathway<-read.table("PTC+_transcript_pep_supp_KEGG.txt",header=T,sep ...

  8. 54-with管理文件操作上下文

    目录 with管理文件操作上下文 with管理文件操作上下文 之前我们使用open()方法操作文件,但是open打开文件后我们还需要手动释放文件对操作系统的占用.其实我们可以更方便的打开文件,即Pyt ...

  9. Flutter Widgets 对话框-Dialog

    注意:无特殊说明,Flutter版本及Dart版本如下: Flutter版本: 1.12.13+hotfix.5 Dart版本: 2.7.0 当应用程序进行重要操作时经常需要用户进行2次确认,以避免用 ...

  10. 30分钟学会Objective-C

    注: 本文首发于我的个人博客:https://evilpan.com/2019/04/05/objc-basics/ 请原谅我的标题党.但是如果你有其他语言的学习经验,要学习Objective-C的语 ...