禁止在正式代码中使用Executors的方法创建线程池
线程池参数详解
我们先看下线程池的定义
public ThreadPoolExecutor(int corePoolSize,
                              int maximumPoolSize,
                              long keepAliveTime,
                              TimeUnit unit,
                              BlockingQueue<Runnable> workQueue,
                              ThreadFactory threadFactory,
                              RejectedExecutionHandler handler)
corePoolSize – 线程池中的常驻线程数, 即使它们是空闲的, 除非 allowCoreThreadTimeOut = true 
maximumPoolSize – 线程池允许的最大线程数
keepAliveTime – 当线程数大于corePoolSize 时,被驱逐的线程存活时间. 
unit – keepAliveTime的单位 
workQueue – 存放任务,在它们执行前
threadFactory – 创建线程是使用的工厂
handler – 线程和队列都饱和之后的处理策略
任务提交后的流程
如果线程数小于corePoolSize,则创建一个新线程,并启动这个线程执行这个任务
如果workQueue还有空间,则把任务提交到workQueue
如果线程数小于maximumPoolSize,则创建一个新线程
其它情况则触发hander#rejectedExecution
handler介绍,ThreadPoolExecutor定义了四种
CallerRunsPolicy - 在提交任务的线程中运行,除非线程池已经被关闭了,这个时候任务会被丢弃
AbortPolicy - 抛RejectedExecutionException异常
DiscardPolicy - 丢弃任务
DiscardOldestPolicy - 丢弃队列中等待时间最长的任务,并提交当前任务,除非线程池已经被关闭了,这个时候任务会被丢弃