ThinkChat🤖让你学习和工作更高效,注册即送10W Token,即刻开启你的AI之旅 广告
[TOC] <br/> > ### 线程池实现原理 ![](https://i.loli.net/2019/03/11/5c85d923986ec.png) ![](https://i.loli.net/2019/03/11/5c85da86c5b37.png) * `ThreadPoolExecutor`执行情况 * 1)如果当前运行的线程少于`corePoolSize`,则创建新线程来执行任务(注意,执行这一步骤需要获取全局锁)。 * 2)如果运行的线程等于或多于`corePoolSize`,则将任务加入`BlockingQueue`。 * 3)如果无法将任务加入`BlockingQueue`(队列已满),则创建新的线程来处理任务(注意,执行这一步骤需要获取全局锁)。 * 4)如果创建新线程将使当前运行的线程超出`maximumPoolSize`,任务将被拒绝,并调用`RejectedExecutionHandler.rejectedExecution()`方法。 <br/> > ### 线程池参数 ``` public ThreadPoolExecutor (int corePoolSize, //核心线程数 int maximumPoolSize, //线程池中允许的最大线程数 long keepAliveTime, //线程池中空闲线程所能允许的最长时间 TimeUnit unit, //时间单位 BlockingQueue<Runnable> workQueue, //任务的阻塞队列 RejectedExecutionHandler handler) //线程池满时对于提交任务的策略 ``` <br/> > ### 线程池满时的拒绝策略`RejectedExecutionHandler ` * `AbortPolicy`:直接抛出异常(默认)。 * `CallerRunsPolicy`:只用调用者所在线程来运行任务。 * `DiscardOldestPolicy`:丢弃队列里最近的一个任务,并执行当前任务。 * `DiscardPolicy`:不处理,丢弃掉。 <br/> > ### 向线程池提交的任务类型 * `execute()`方法用于提交不需要返回值的任务,所以无法判断任务是否被线程池执行成功。 * `submit()`方法用于提交需要返回值的任务。线程池会返回一个`future`类型的对象,通过这个`future`对象可以判断任务是否执行成功,并且可以通过`future`的`get()`方法来获取返回值,`get()`方法会阻塞当前线程直到任务完成。 <br/> > ### `FixedThreadPool` ``` public static ExecutorService newFixedThreadPool(int nThreads) { return new ThreadPoolExecutor(nThreads, nThreads, 0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<Runnable>()); } ``` * `FixedThreadPool`固定线程数的线程池,`corePoolSize`和`maximumPoolSize`都被设置为创建`FixedThreadPool`时指定的参数`nThreads`。 * 当线程池中的线程数大于`corePoolSize`时,`keepAliveTime`为多余的空闲线程等待新任务的最长时间,超过这个时间后多余的线程将被终止。这里把`keepAliveTime`设置为0L,意味着多余的空闲线程会被立即终止。 * 使用`FixedThreadPool`时,`keepAliveTime`和`RejectedExecutionHandler`均无效。 * `FixedThreadPool`使用无界队列`LinkedBlockingQueue`作为线程池的工作队列,注意:当线程池中的线程阻塞时,新任务不断的添加到无界队列`LinkedBlockingQueue`中,任务的添加速度大于线程池的处理速度,任务队列会越来越长,会造成内存被这个队列撑满。 ![](https://i.loli.net/2019/03/11/5c85dfb84ea23.png) > ### `SingleThreadExecutor` ``` public static ExecutorService newSingleThreadExecutor() { return new FinalizableDelegatedExecutorService(new ThreadPoolExecutor(1, 1, 0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<Runnable>())); } ``` * `SingleThreadExecutor`是使用单个`worker`线程的`Executor`。 * `SingleThreadExecutor`的`corePoolSize`和`maximumPoolSize`被设置为1。其他参数与`FixedThreadPool`相同。`SingleThreadExecutor`使用无界队列`LinkedBlockingQueue`作为线程池的工作队列。 ![](https://i.loli.net/2019/03/11/5c85e98350e00.png) > ### `CachedThreadPool` ``` public static ExecutorService newCachedThreadPool() { return new ThreadPoolExecutor(0, Integer.MAX_VALUE, 60L, TimeUnit.SECONDS, new SynchronousQueue<Runnable>()); } ``` * `CachedThreadPool`的`corePoolSize`被设置为0,即corePool为空;`maximumPoolSize`被设置为`Integer.MAX_VALUE`,即`maximumPool`是无界的。这里把`keepAliveTime`设置为60L,意味着`CachedThreadPool`中的空闲线程等待新任务的最长时间为60秒,空闲线程超过60秒后将会被终止。 * `CachedThreadPool`使用没有容量的`SynchronousQueue`作为线程池的工作队列,但`CachedThreadPool`的`maximumPool`是无界的。这意味着,如果主线程提交任务的速度高于`maximumPool`中线程处理任务的速度时,`CachedThreadPool`会不断创建新线程。极端情况下,`CachedThreadPool`会因为创建过多线程而耗尽CPU和内存资源。 ![](https://i.loli.net/2019/03/11/5c85ea527de2c.png) > ### ` ScheduledThreadPoolExecutor` * `ScheduledThreadPoolExecutor`继承自`ThreadPoolExecutor`。它主要用来在给定的延迟之后运行任务,或者定期执行任务。 * `DelayQueue`是一个无界队列 ![](https://i.loli.net/2019/03/11/5c85ebac87ccd.png)