线程池

线程池是一个可以复用线程的技术

不用线程池

用户每发起一个请求,后台就需要创建一个新线程来处理,下次新任务来了肯定又要创建新线程。而创建新线程的开小很大,请求过多时,肯定会产生大量的线程出来,严重影响性能

ExecutorService接口-线程池接口

如何得到线程池对象

  1. 方式一: 使用ExecutorService的实现类ThreadPoolExecutor自创建一个线程池对象
  2. 方式二:使用Executors(线程池的工具类)调用方法返回不同特点的线程池对象

ThreadPoolExecutor

构造器

public ThreadPoolExecutor(
    int corePoolSize, int maximumPooSize, long keepAliveTime, TimeUnit unit, BlockingQueue<Runnable> workQueue, ThreadFactory threadFactory, RejectedExecutionHandler handler
)
  1. corePoolSize:指定线程池的核心线程数量
  2. maximumPooSize:指定线程池的最大线程数量
  3. keepAliveTime:指定临时线程存活时间
  4. unit: 指定临时线程存货的时间单位(秒、分、时、天)
  5. workQueue:指定线程池任务队列
  6. threadFactory:指定线程池的线程工厂,负责创建线程
  7. handler:指定线程池的任务拒绝策略(线程都在忙,任务队列也满了的时候,新任务来了怎么处理)

线程池的注意事项

  1. 临时线程什么时候创建 新任务提交时发现核心线程都在忙,任务队列也满了,并且还可以创建临时线程,此时才会创建
  2. 什么时候开始拒绝新任务 核心线程和临时线程都在忙,任务队列也满了,新的任务过来的时候才会开始拒绝任务。

ExecutorService的常用方法

方法名称 说明
void execute(Runnable command) 执行Runnable任务
Future 执行Callable任务,返回未来任务对象,用于获取线程返回的结果
void shutdown 等全部任务执行完毕后,再关闭线程池
List 立刻关闭线程池,停止正在执行的任务,并返回队列中未执行的任务。

新任务拒绝策略

策略|详解 ThreadPoolExecutor.AbortPolicy|丢弃任务并抛出RejectedExecutionException异常,是默认的策略 ThreadPoolExecutor.DiscardPolicy|丢弃任务,但是不抛出异常,不推荐 ThreadPoolExecutor.DiscardOldestPolicy|抛弃队列中等待最久的任务,然后把当前任务加入队列 ThreadPoolExecutor.CallerRunsPolicy||由主线程复杂调用任务的run方法从而绕过线程池直接执行

Executors

是一个线程池的工具类,提供了很多静态方法用于返回不同特点的线程池对象 alt text 这些方法的底层,是通过ThreadPoolExecutor创建的线程池对象

Executors使用可能存在的陷阱

大型并发系统环境中使用Executors如果不注意可能会出现系统风险。 alt text OOM为内存问题 阿里直接不允许用Executors创建线程池

核心线程数该怎么选-经验

  1. 计算密集型任务: 核心线程数 = CPU的核数 + 1
  2. IO密集型任务: 核心线程数 = CPU核数 * 1

本文章使用limfx的vscode插件快速发布