1. 线程池相关类图
2. 相关类讲解
- Executor:基础的接口,初衷是讲任务提交和任务执行细节进行解耦,有一个唯一的方法:
void execute(Runnable command);
- ExecutorService:提供了service的管理功能,如shutdown等方法;也提供了更加全面的任务提交机制,返回的不是void,而是Future的submit方法。
<T> Future<T> submit(Callable<T> task);
<T> Future<T> submit(Runnable task, T result);
Future<?> submit(Runnable task);
- ThreadPoolExecutor、ScheduledThreadPoolExecutor、ForkJoinPool:Java标准类库提供的基础实现。其中ScheduledThreadPoolExecutor是ThreadPoolExecutor的扩展,主要是增加了调度逻辑。ForkJoinPool则是为ForkJoinTask定制的线程池。
3. Executors
从简化使用的角度,提供了创建线程池的各种方便的静态工厂方法。主要提供的方法有:
- newCachedThreadPool()
- newFixedThreadPool(int nThreads)
- newSingleThreadExecutor()
- newScheduledThreadPool(int corePoolSize)
- newWorkStealingPool(int parallelism)
开发者都是利用 Executors 提供的通用线程池创建方法,去创建不同配置的线程池,主要区别在于不同的 ExecutorService 类型或者不同的初始参数。
但是,我们仍然可以直接使用ThreadPoolExecutor等构造方法来创建线程池,这就需要我们了解线程池的构造。
4. 线程池的构造
4.1. 线程池的基本参数
- int corePoolSize:线程池保有的最小线程数。有些项目很闲,但是不能把人都撤了,至少要留corePoolSize个人坚守阵地【100】
- int maximumPoolSize:表示线程池创建的最大线程数。当项目很忙的时候,就要增加人,但是也不能无限添加,最多只能加到maxmunPoolSize个人;当项目不忙的时候,就要撤人,最多能撤到corePoolSize个人【500】
- long keepAliveTime & TimeUnit unit:一个线程如果在一段时间都没有执行任务,说明很闲。这个keepAliveTime和unit就是用来定义“一段时间”的参数。也就是说,如果一个线程空闲了keepAliveTime & unit这么久,而且线程池中线程数大于corePoolSize,那么这个空闲的线程就要被回收了。【10 s】
- BlockingQueue workQueue:工作队列。负责存储用户提交的各个任务。 【100】
- ThreadFactory threadFactory:通过这个参数可以自定义如何创建线程。
- RejectedExecutionHandler handler:自定义拒绝策略。如果线程池中的所有的线程都在忙,并且工作队列也满了,那么此时提交任务,线程池就会拒绝接收。【CallerRunsPolicy】