先学如下几个概念
当前线程池的大小,最大线程池大小,核心线程池的大小
当前线程池大小:表示当前工作者线程的数量。
最大线程池大小:表示工作者线程的最大数量。
核心线程池大小:表示工作者线程数量不大于最大工作者线程池的大小。
这个概念存在以下关系
当前线程池的大小 < 核心线程池的大小 < 最大线程池的大小
核心线程池的大小 < 当前线程池的大小 < 最大线程池的大小
java 线程池的构造函数
public ThreadPoolExecutor(int corePoolSize,
int maxinumPoolSize,
long keepAliveTime,
TimeUnit unit,
BlockingQueue<Runable> workQueue,
ThreadFactory threadFactory,
RejectedExecutionHandler handler);
这里主要介绍几个不常见的参数
keepAliveTime :代表当当前线程数大于核心线程数的时候空闲线程休闲的时候能够存活的时间
unit:时间单位
threadFactory: 对工作者线程的创建进行的一种封装
handler: 拒绝策略
工作模式
在初始状态下,每当接收到一个任务,线程池就会创建一个工作者线程,随着任务量的增加,线程池大小亦会变大,随着线程池的大小达到核心线程池的大小的时候,这时如果在有新的任务到达,就会将这些任务存储到队列当中去。每当线程池的工作者线程一空闲,就会去线程池当中取出任务,在继续对其执行,如果消费者的速度慢于生产者,也就是慢于任务的产生,就会继续扩大线程池的工作者线程的数量,直到当前线程池大小达到最大线程池大小。这时如果在任务还没有处理完毕的前提下,又有新的任务到来,线程池就会执行某些拒绝策略对任务的提交进行拒绝
handler 拒绝策略(ThreadPoolExecutor提供的实现类)
ThreadPoolExcutor.AbortPolicy | 直接抛出异常 |
ThreadPoolExcutor.DiscardPolicy | 丢弃当前被拒绝的任务,并没有做出任何动作 |
ThreadPoolExcutor.DiscardOldestPolicy | 将工作队列中最老的任务丢掉,然后重新尝试接纳被拒绝的任务 |
ThreadPoolExcutor.CallerRunsPolicy | 在客户端线程中执行被拒绝的任务 |
Executors 工具类
方法 | 通用条件以及注意实现 |
newCachedThreadPool() | 适合用于执行大量耗时较短且提交比较频繁的任务。如果提交的任务的执行耗时较长,那么可能导致线程池中的工作者线程无限地增加,最后导致过多的上下文切换,从而使得整体变慢。 |
newCachedThreadPool(ThreadFactory threadFactory) | |
newFixedThredPool(int nThreads) | 由于该方法返回的线程池的核心线程池大小等于其最大线程池大小,因此该线程池中的工作者线程永远不会超时。我们不需要该线程池时主动将其关闭。 |
newFixedThredPool(nt nThreads,ThreadFactory threadFactory) | |
newSingleThreadExcutor() | 适合用来实现单/多生成者-单消费者模式 |
newSingleThreadExcutor(ThreadFactory threadFactory) |
各个方法的返回值:
方法 | 返回值 |
Executor.newCachedThreadPool() | new ThreaPoolExecutor(0,Integer.Max_Value,60L,Timeunit.SECONDS,new SynchronousQueue<Runable>()); |
Executor.newFixedThreadPool(int nThreads) | new ThreaPoolExecutor(nThreads,nThreads, 0 ,Timeunit.SECONDS,new LinkedBlockingQueue<Runable>()); |
Executor.newSingleThreadPool(int nThreads) | Executor.newFixedThreadPool(1); |