线程池的应用及实现原理

使用线程池的原因

线程是不是越多越好?

  1. 线程在java中是一个对象,创建销毁都需要时间开销,如果比任务执行时间都长,就不合算
  2. java对象占用堆内存,线程太多会占用很多系统内存
  3. 操作系统需要频繁切换线程(大家都想被运行),影响性能

所以,线程池的推出,就是为了方便的控制线程数量

线程池相关概念

1、线程池管理器

用于创建并管理线程池,包括线程池的创建,销毁,添加新任务

2、工作线程

线程池中的线程,并未有任务时处于等待状态,可以循环执行任务

3、任务接口

每个任务必须实现的接口,以供工作线程调度任务的执行,它主要规定了任务的入口,任务完成的收尾工作,任务的执行状态等

4、任务队列

用于存放没有处理的任务,提供了一种缓冲机制

线程池API - 接口定义和实现类

在这里插入图片描述

ExcutorService 中的方法

在这里插入图片描述

ScheduledExcutorService 中的补充方法

在这里插入图片描述

理解:

  1. 第三个方法的调度方式:如果方法执行时间 > 固定间隔, 则以执行时间为主,忽略固定间隔
  2. 第四个方法的调度方式:如果方法执行时间 > 固定间隔,则仍然以固定间隔为主

Excutors工具类

使用:(以下两种方式是等价的!)

  1. Executors.newFixedThreadPool( 5)
  2. ThreadPoolExcutor threadPoolExcutor = new ThreadPoolExcutor(5, 5, 0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue());

一、newFixedThreadPool(int nThreads)

创建一个固定大小,任务队列无界的线程池。核心线程数 = 最大线程数

二、newCachedThreadPool()

  1. 创建一个大小无界的缓冲线程池
  2. 它的队列是一个同步队列
  3. 任务加入到池中,如果池中有空闲线程,则用空闲线程执行,如果没有,则创建新线程执行
  4. 池中的线程空闲超过60s将被销毁释放
  5. 线程数随任务的多少而变化
  6. 适用于执行耗时较小的异步任务
  7. 池的核心线程数 = 0,最大线程数 = Integer.MAX_VALUE

三、newSingleThreadExcutor()

  1. 只有一个线程来执行无界队列的单一线程池
  2. 该线程池确保任务按加入的顺序一个一个依次执行
  3. 当唯一的线程因为任务异常终止时,将创建一个新的线程来继续执行后续的任务
  4. 与newFixedThreadPool(1)的区别是,单一线程池的大小是方法内硬编码,不可改变

四、newScheduledThreadPool(int corePoolSize)

  1. 能定时执行任务的线程池
  2. 该池的核心线程数又参数指定,最大线程数 = Integer.MAX_VALUE

线程池原理 - 任务excute过程

在这里插入图片描述

线程池终止

一、threadPoolExcutor.shutdown()

调用shutdown()方法后,将不接收新的任务,会等待已有任务(队列+最大线程数)全部执行结束后关闭线程池

二、threadPoolExcutor.shutdownNow()

  1. 调用shutdownNow()后,不管有没有任务在执行,都立刻关闭线程池,没跑完的任务会全部抛出异常
  2. 返回值为List ,就是还在队列中的任务

线程数量

问题:那如何确定合适数量线程呢?

建议:

  1. 计算型任务:cpu数量的1 - 2倍
  2. IO型任务,要根据具体IO阻塞时长进行考量,适当增加线程数(比如tomcat最大是200)
  3. 也可以根据需要在最小数量与最大数量间自动增减线程数(比如newCachedThreadPool)

达标建议:生产环境CPU使用率达到80%,就算比较合理了

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值