一,为什么要使用线程池

池化技术现在已经应用的很广法了,数据库连接池,Http连接池,线程池等等都是该思想的应用,它的核心目的就是减少资源消耗,提高资源的利用率。

使用线程池的好处:

  • 降低资源消耗,重复的利用已创建的线程,减少线程的创建与销毁。

  • 提高相应效率,当任务到达时,不需要去创建线程,而是直接执行。

  • 提高线程的可管理性,线城是稀缺资源,如果无限创建,会消耗系统资源,而且还会降低系统稳定性,使用线程池可以统一分配管理和监控。

Exector框架

Exector框架不仅包括了线程池的管理,还提供了线程工厂,队列以及拒绝策略等,Exector框架让并发编程变得更加简单。而且还能避免this逃逸问题。

Executor框架结构

Executor框架主要有三大部分组成(任务,任务的执行,异步计算的结果)下面我们将详细介绍一下。

任务(Runable、Callable)

执行任务需要实现的Runable接口或Callable接口,他俩的实现类都可以被ThreadPoolExector或者ScheduledThreadPoolExecutor执行、

任务的执行(Executor)

包含任务执行机制的核心接口Executor,以及继承自该皆苦的ExecutorService接口。ThreadPoolExecutor和ScheduledThreadPool这两个关键类都实现了ExecutorService接口。

注意:通过查看ScheduledThreadPoolExecutor源代码我们发现其实它实际上是继承了ThreadPoolExecutor并实现了ScheduledExecutorService,而ScheduledExecutorSerivice又实现了ExecutorService.

异步计算的结果(Future)

Future接口以及Future接口的实现类FutureTask类都可以代表异步计算的结果。

当我们把Runable或Callable接口的实现类提交给ThreadPoolExecutor或ScheduledThreadPoolExecutor执行。调用Sumit方法时会返回一个FutureTask对象。

其具体如下:

  • 首先创建Runbale/Callable接口任务对象。

  • 其次把创建完的对象直接交给ExecutorService执行。

  • 如果执行ExecutorService.submit,将返回一个实现了Future接口的对象。由于FutureTask实现了Runable,也可以直接创建FutureTask,直接交给ExecutorService执行。

  • 最后,主线程执行FutureTask.get(0方法等待子线程执行完成,也可以执行cancel方法取消任务。

ThreadPoolExecutor类简单介绍

ThreadPoolExecutor中三个重要参数

  • corePoolSize:核心线程数线程数定义了最小可以同时同时运行的线程数量。

  • maximumPoolSize:当队列中存放的任务达到最大任务数量时,当前可运行的线程数数量变成最大线程数

  • workQueue:当新的任务进来的时候,会先判断当前运行的线程数量是否达到核心线程数,如果达到的话,就会被存放到队列中。

ThreadPoolExecutor其他常见参数:

  • unit:参数的时间单位

  • keepAliveTime:当线程池中的数量超过核心线程数时,如果没有新的任务提交,核心线程之外的线程不会立刻销毁,二是等到,超过该时间才会销毁

  • handler:拒绝策略。这个后面详细解读

  • threadFactory:executor创建新线程的时候会用到

拒绝策略:

如果当前同时运行的线程数量达到最大线程数,并且队列中已经放满任务的时候,那么就会使用拒绝策略、

  • AbortPolicy:抛出RejectedExecutionException来拒绝新的任务处理。

  • CallerRunsPolicy:调用执行自己的线程执行任务,也就是直接再调用execute方法的线程中运行run被拒绝的任务,如果执行程序已关闭,则会丢弃该任务,因此这种策略会降低对于新任务提交速度,影响程序的整体性能,如果您的应用程序可以承受此延迟并且你要求任何一个任务请求都要被执行的话,你可以选择这个策略。

  • DiscardPolicy:不处理任务,直接丢弃掉。

  • DiscardOldestPolicy:此策略将丢弃最早的未处理的任务请求。

为什么推荐使用THreadPoolExecutor构造函数创建线程池。

Executors返回线程池对象的弊端如下:

CachedThreadPool,ScheduledThreadPool:允许创建的线程数量未Integer.MAX_VALUE,可能会创建大量线程,从而导致OOM

FixedThreadPool,SingleThreadExecutor:允许队列长度未Inter.MAX_VALUE,可能堆积大量请求,从而导致OOM。