使用线程池的目的

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

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

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

优点

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

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

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

创建线程池的方式

 在 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. CSS3动画之animation-timing-function中的stepshan shu

    1.概念 animation-timing-function是规定动画的速度曲线,一般使用的是cubic-bezier() 控制动画曲线的,属性值一般有ease/ease-in/ease-out等,而 ...

  2. tensorflow1.x及tensorflow2.x不同版本实现验证码识别

    近一个假期,入坑深度学习,先从能看得着的验证码识别入门.从B站看了几天的黑马程序员的“3天带你玩转python深度学习后“,一是将教程中提到的代码一一码出来:二是针对不同的tensorflow版本,结 ...

  3. os.path获取当前路径及父路径

    import os pwd = os.getcwd() print("当前目录: " + pwd) father_path_method1 = os.path.dirname(pw ...

  4. Redis秒杀实战-微信抢红包-秒杀库存,附案例源码(Jmeter压测)

    导读 前二天我写了一篇,Redis高级项目实战(点我直达),SpringBoot整合Redis附源码(点我直达),今天我们来做一下Redis秒杀系统的设计.当然啦,Redis基础知识还不过关的,先去加 ...

  5. Laravel 避免 Trying to get property of non-object 错误的六种方法 [新增第六种 data_get]

    在使用链式操作的时候,例如: return $user->avatar->url;如果 $user->avatar 为 null,就会引起 (E_ERROR) Trying to g ...

  6. ios .framework动态库重签名

    真机上运行.framework时,如果报 dyld'dyld_fatal_error:dyld: Library not loaded: @rpath/XX.framework/XX Referenc ...

  7. cg语言学习&&阳春白雪GPU编程入门学习

    虽然所知甚少,但康大的<GPU编程与Cg编程之阳春白雪下里巴人>确实带我入了shader的门,在里面我第一次清晰地知道了“语义”的意思,非常感谢. 入门shader,我觉得可以先读3本书: ...

  8. 总结一篇shell调试技巧及常见的脚本错误

      #常见的调试命令工具 1.使用bash命令参数调试 #使用 [root@game ~]# sh [-xvn] test.sh #参数解释: -x:将执行的脚本内容输出出来,可以看到执行的过程 -n ...

  9. 高可用集群corosync+pacemaker之pcs安装使用

    前文我们介绍了高可用集群corosync+pacemaker的集群管理工具crmsh的常用命令的使用,回顾请参考https://www.cnblogs.com/qiuhom-1874/tag/crms ...

  10. Sender(agumaster_crawler)->RabbitMq->Reciever(agumaster)

    发送方: package com.heyang.agumasterCrawler; import java.util.List; import org.springframework.beans.fa ...