使用线程池的目的

  • 线程是稀缺资源,不能频繁的创建

  • 解耦作用:线程的创建与执行完全分开,方便维护

  • 将其放入一个池子中,可以给其他任务进行复用

优点

  • 降低资源消耗,通过重复利用已创建的线程来降低线程创建和销毁造成的消耗。

  • 提高相应速度,当任务到达时,任务可以不需要的等到线程创建就能立即执行。

  • 提高线程的可管理性,线程是稀缺资源,如果无限制的创建,不仅仅会消耗系统资源,还会降低体统的稳定性,使用线程可以进行统一分配,调优和监控

创建线程池的方式

 在 JDK 1.5 之后推出了相关的 api,常见的创建线程池方式有以下三种:

  • Executors.newCachedThreadPool():无限线程池,线程池动态扩容

  • Executors.newFixedThreadPool(nThreads):创建固定大小的线程池

  • Executors.newSingleThreadExecutor():创建单个线程的线程池

  • Executors.newScheduledThreadPool():定时执行的线程池

 JDK1.8新增

  • Executors.newWorkStealingPool(): newWorkStealingPool适合使用在很耗时的操作,但是newWorkStealingPool不是ThreadPoolExecutor的扩展,它是新的线程池类ForkJoinPool的扩展,但是都是在统一的一个Executors类中实现,由于能够合理的使用CPU进行对任务操作(并行操作),所以适合使用在很耗时的任务中

但是在阿里巴巴开发规约中对线程池的创建有以下几个强制要求:

可以看到规约是不允许使用Executors直接创建线程池的,而要通过ThreadPoolExecutor的方式创建

1 public static ExecutorService newCachedThreadPool() {
2 return new ThreadPoolExecutor(0, Integer.MAX_VALUE,
3 60L, TimeUnit.SECONDS,
4 new SynchronousQueue<Runnable>());
5 }

我们看到这三种方式的源码也是通过ThreadPoolExecutor的方式来创建的,接下来我们看一下ThreadPoolExecutor的API

public ThreadPoolExecutor(int corePoolSize,
int maximumPoolSize,
long keepAliveTime,
TimeUnit unit,
BlockingQueue<Runnable> workQueue,
ThreadFactory threadFactory,
RejectedExecutionHandler handler)

这几个核心参数的作用:

  • corePoolSize 核心线程池大小

  • maximumPoolSize 为线程池最大线程大小

  • keepAliveTime线程池中超过 corePoolSize 数目的空闲线程最大存活时间

  • unit  keepAliveTime的时间单位
  • workQueue 用于存放任务的阻塞队列

  • threadFactory 线程工厂,可以自定义线程名称
  • handler 当队列和最大线程池都满了之后的拒绝策略

    • AbortPolicy:处理程序遭到拒绝将抛出运行时 RejectedExecutionException
    • CallerRunsPolicy:线程调用运行该任务的 execute 本身。此策略提供简单的反馈控制机制,能够减缓新任务的提交速度
    • DiscardPolicy:不能执行的任务将被删除
    • DiscardOldestPolicy:如果执行程序尚未关闭,则位于工作队列头部的任务将被删除,然后重试执行程序(如果再次失败,则重复此过程)

工作原理

  • 当线程池小于corePoolSize时,新提交任务将创建一个新线程执行任务,即使此时线程池中存在空闲线程

  • 当线程池达到corePoolSize时,新提交任务将被放入 workQueue 中,等待线程池中任务调度执行

  • 当workQueue已满,且 maximumPoolSize 大于 corePoolSize 时,新提交任务会创建新线程执行任务

  • 当提交任务数超过 maximumPoolSize 时,新提交任务由 RejectedExecutionHandler 处理

  • 当线程池中超过corePoolSize 线程,空闲时间达到 keepAliveTime 时,关闭空闲线程

  • 当设置allowCoreThreadTimeOut(true) 时,线程池中 corePoolSize 线程空闲时间达到 keepAliveTime 也将关闭

线程池大小创建的原则

  • IO 密集型任务:由于线程并不是一直在运行,所以可以尽可能的多配置线程,比如 CPU 个数 * 2

  • CPU 密集型任务(大量复杂的运算)应当分配较少的线程,比如 CPU 个数相当的大小

附:SpringBoot线程池工具类

Java多线程--创建和使用线程池的更多相关文章

  1. java多线程总结五:线程池的原理及实现

    1.线程池简介:     多线程技术主要解决处理器单元内多个线程执行的问题,它可以显著减少处理器单元的闲置时间,增加处理器单元的吞吐能力.        假设一个服务器完成一项任务所需时间为:T1 创 ...

  2. (Java多线程系列九)线程池

    线程池 1.什么是线程池 线程池是指在初始化一个多线程应用程序过程中创建一个线程集合,然后在需要执行新的任务时重用这些线程而不是新建一个线程.线程池中线程的数量通常取决于可用内存数量和应用程序的需求. ...

  3. Java多线程并发04——合理使用线程池

    在此之前,我们已经了解了关于线程的基本知识,今天将为各位带来,线程池这一技术.关注我的公众号「Java面典」了解更多 Java 相关知识点. 为什么使用线程池?线程池做的工作主要是控制运行的线程的数量 ...

  4. java多线程详解(7)-线程池的使用

    在前面的文章中,我们使用线程的时候就去创建一个线程,这样实现起来非常简便,但是就会有一个问题: 如果并发的线程数量很多,并且每个线程都是执行一个时间很短的任务就结束了, 这样频繁创建线程就会大大降低系 ...

  5. java多线程(四)-自定义线程池

    当我们使用 线程池的时候,可以使用 newCachedThreadPool()或者 newFixedThreadPool(int)等方法,其实我们深入到这些方法里面,就可以看到它们的是实现方式是这样的 ...

  6. java多线程系列六、线程池

    一. 线程池简介 1. 线程池的概念: 线程池就是首先创建一些线程,它们的集合称为线程池. 2. 使用线程池的好处 a) 降低资源的消耗.使用线程池不用频繁的创建线程和销毁线程 b) 提高响应速度,任 ...

  7. (CSDN迁移)JAVA多线程实现-单线程化线程池newSingleThreadExecutor

    JAVA通过Executors提供了四种线程池,单线程化线程池(newSingleThreadExecutor).可控最大并发数线程池(newFixedThreadPool).可回收缓存线程池(new ...

  8. Java 多线程(五)—— 线程池基础 之 FutureTask源码解析

    FutureTask是一个支持取消行为的异步任务执行器.该类实现了Future接口的方法. 如: 取消任务执行 查询任务是否执行完成 获取任务执行结果(”get“任务必须得执行完成才能获取结果,否则会 ...

  9. java核心-多线程(6)-线程池-ThreadPoolExecutor

    1.java多线程编程少不了使用线程池,线程池相关的工具类所在jdk包,java.util.concurrent 2.使用示例 demo1 public class ThreadPoolDemo { ...

随机推荐

  1. 大数据理论篇HDFS的基石——Google File System

    Google File System 但凡是要开始讲大数据的,都绕不开最初的Google三驾马车:Google File System(GFS), MapReduce,BigTable. 为这一切的基 ...

  2. springMVC入门(五)------统一异常处理

    简介 系统中异常包括两类:预期异常和运行时异常RuntimeException,前者通过异常捕获获取异常信息,后者需通过规范代码.提高代码路绑定减少运行时异常的发生 异常处理思路:无论dao层.ser ...

  3. 牛客网PAT练兵场-福尔摩斯的约会

    题目地址:https://www.nowcoder.com/pat/6/problem/4040 题意:模拟题,循环找相同的字母,但是注意题目的坑 /** * *作者:Ycute *时间:2019-1 ...

  4. 从零开始的SpringBoot项目 ( 七 ) 统一返回结果集Result 和 异常处理

    import java.io.Serializable; import lombok.Data; import org.springframework.http.HttpStatus; @Data p ...

  5. 基于Nodejs的sequelize操纵数据库

    ## 使用基于ORM架构的sequelize操纵数据库 ### 1.技术背景 ```Sequelize是一个基于promise的关系型数据库ORM框架,*********************技术文 ...

  6. [CSP-S2019]格雷码 题解

    CSP-S2 2019 D1T1 考场上第一遍读题的时候感觉不是很一眼……不是很符合D1T1的气质 之前完全没听说过格雷码是什么玩意,还是我太菜了 仔细读题后发现应该是有规律可循的 赛后据说有$O(1 ...

  7. swagger的导出

    swagger-export是一个提供swagger文档导出功能的服务,不依赖于具体的API接口服务实现,你可以很方便地导出html和pdf两种格式的静态文档.源码来自swagger导出静态API文档 ...

  8. GA教程:使用自定义变量来扩展高级细分

    http://www.wocaoseo.com/thread-64-1-1.html 您可以使用自定义变量来扩展高级细分的范围. 高级细分依据的标准是用户的会话(访问)数据.如果某个访问者在指定日期范 ...

  9. C#封装定时执行任务类

    a.日常开发中经常会遇到定时去执行一些操作,比如定时更新数据.A类需要做我们写个Timer定时去取数据,这时候B类,C类也需要做这样的事情,是不是需要写三次重复代码? 这时候把timer封装成一个帮助 ...

  10. 贝塞尔曲线(B-spline)的原理与应用

    什么是贝塞尔曲线? 贝塞尔曲线(Bézier curve),又称贝兹曲线或贝济埃曲线,是应用于二维图形应用程序的数学曲线. 来源 贝塞尔曲线于1962,由法国工程师皮埃尔·贝塞尔(Pierre Béz ...