「这是我参与11月更文挑战的第7天,活动详情查看:2021最后一次更文挑战」@[toc]
五.线程池
②.构造方法
ThreadPoolExecutor有四个参数不同的构造方法,其实都是用参数最多的那个构造方法去构造的;
ThreadPoolExecutor(int,int,long,TimeUnit,BlockingQueue<Runnable>);
ThreadPoolExecutor(int,int,long,TimeUnit,BlockingQueue<Runnable>,ThreadFactory);
ThreadPoolExecutor(int,int,long,TimeUnit,BlockingQueue<Runnable>,RejectedExecutionHandler);
ThreadPoolExecutor(int,int,long,TimeUnit,BlockingQueue<Runnable>
,ThreadFactory,RejectedExecutionHandler);
/*
*五个参数的构造方法
*/
public ThreadPoolExecutor(int corePoolSize,
int maximumPoolSize,
long keepAliveTime,
TimeUnit unit,
BlockingQueue<Runnable> workQueue) {
this(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue,
Executors.defaultThreadFactory(), defaultHandler);
}
拿第一个举例,看到其实是调用了七个参数的构造方法,使用默认的ThreadFactory和拒绝策略。
参数含义:
| 参数 | 使用 | |
|---|---|---|
| corePoolSize | 留在池中的线程数,即使它们是空闲的,除非{@code allowCoreThreadTimeOut}设置 | 这个参数是否生效取决于allowCoreThreadTimeOut变量的值,该变量默认是false,即对于核心线程没有超时限制,所以这种情况下,corePoolSize参数是起效的。 如果allowCoreThreadTimeOut为true,那么核心线程允许超时,并且超时时间就是keepAliveTime参数和unit共同决定的值,这种情况下,如果线程池长时间空闲的话最终存活的线程会变为0,也即corePoolSize参数失效。 |
| maximumPoolSize | 池中允许的最大线程数 | 线程池中最大的存活线程数。这个参数比较好理解,对于超出corePoolSize部分的线程,无论allowCoreThreadTimeOut变量的值是true还是false,都会超时,超时时间由keepAliveTime和unit两个参数算出。 |
| keepAliveTime | 当线程数大于核心数时,这是多余的空闲线程在终止之前等待新任务的最大时间。 | 超时时间。 |
| unit | {@code keepAliveTime}参数的时间单位 | 超时时间的单位(TimeUnit类中有7种静态属性),天,小时,分,秒,毫秒,微秒,纳秒等,与keepAliveTime参数共同决定超时时间。 |
| workQueue | 用于在任务执行之前保存它们的队列。这个队列将只保存由{@code execute}方法提交的{@code Runnable}任务。 | 当调用execute方法时,如果线程池中没有空闲的可用线程,那么就会把这个Runnable对象放到该队列中。这个参数必须是一个实现BlockingQueue接口的阻塞队列,因为要保证线程安全。 有一个要注意的点是,只有调用execute方法,才会向这个队列中添加任务,submit方法提交任务时,如果没有可用的线程也不会直接扔掉,AbstractExecutorService类中对submit方法的实现,submit方法只是把传进来的Runnable对象或Callable对象包装成一个新的Runnable对象,然后调用execute方法,并将包装后的FutureTask对象作为一个Future引用返回给调用者。Future的阻塞特性实际是在FutureTask中实现的。 |
| threadFactory | 执行程序创建新线程时要使用的工厂 | 线程工厂类。用于在需要的时候生成新的线程。默认实现是Executors.defaultThreadFactory(),即new 一个Thread对象,并设置线程名称,daemon等属性。 |
| handler | 当执行因达到线程边界和队列容量而阻塞时要使用的处理程序 | 表示当拒绝处理任务时的策略,有以下四种取值: ThreadPoolExecutor.AbortPolicy:丢弃任务并抛出RejectedExecutionException异常。 ThreadPoolExecutor.DiscardPolicy:也是丢弃任务,但是不抛出异常。 ThreadPoolExecutor.DiscardOldestPolicy:丢弃队列最前面的任务,然后重新尝试执行任务(重复此过程) ThreadPoolExecutor.CallerRunsPolicy:由调用线程处理该任务 |
③比较重要的几个方法
| 方法 | 参数/返回值 | |
|---|---|---|
| execute() | Runnable command / void | 在Executor接口中声明, ThreadPoolExecutor中实现, 是ThreadPoolExecutor的核心方法, 通过这个方法可以提交一个任务给线程池,由线程池去执行。 |
| submit() | Runnable task / Future<?> Runnable task, T result / Future Callable task / Future | 在ExecutorService中声明,在AbstractExecutorService中实现,通过这个方法可以提交一个任务给线程池,但是和execute()有区别,可以通过Future类型拿到返回值。 |
| shutdown() | void / void | 启动一个有序的关闭,先前提交的任务将被执行,但不接受新的任务。如果已经关闭,则调用没有额外效果。 |
| shutdownNow() | void / List | 尝试停止所有正在执行的任务,停止正在等待的任务的处理,并返回正在等待执行的任务的列表。当从这个方法返回时,这些任务将从任务队列中被排干(删除)。 |
未完待续。。