1、为什么使用线程池?
- 降低资源消耗。通过重复利用已创建的线程降低线程创建和销毁造成的消耗。
- 提高响应速度。当任务到达时,可以不需要等到线程创建就能立即执行。
- 提高线程的可管理性。统一管理线程,避免系统创建大量同类线程而导致消耗完内存。
2、线程池执行原理?
1. 当线程池里存活的线程数小于核心线程数 corePoolSize 时,这时对于一个新提交的任务,线程池会创建一个线程去处理任务。当线程池里面存活的线程数小于等于核心线程数 corePoolSize 时,线程池里面的线程会一直存活着,就算空闲时间超过了 keepAliveTime ,线程也不会被销毁,而是一直阻塞在那里一直等待任务队列的任务来执行。
2. 当线程池里面存活的线程数已经等于corePoolSize了,这是对于一个新提交的任务,会被放进任务队列workQueue排队等待执行。
3. 当线程池里面存活的线程数已经等于 corePoolSize 了,并且任务队列也满了,假设maximumPoolSize>corePoolSize ,这时如果再来新的任务,线程池就会继续创建新的线程来处理新的任务,知道线程数达到 maximumPoolSize ,就不会再创建了。
4. 如果当前的线程数达到了 maximumPoolSize ,并且任务队列也满了,如果还有新的任务过来,那就直接采用拒绝策略进行处理。默认的拒绝策略是抛出一个RejectedExecutionException异常。
3、线程池的核心参数
publicThreadPoolExecutor(intcorePoolSize, intmaximumPoolSize, longkeepAliveTime, TimeUnitunit, BlockingQueue<Runnable>workQueue, ThreadFactorythreadFactory, RejectedExecutionHandlerhandler);
1、 corePoolSize :当有新任务时,如果线程池中线程数没有达到线程池的基本大小,则会创建新的线
程执行任务,否则将任务放入阻塞队列。当线程池中存活的线程数总是大于 corePoolSize 时,应该考虑
调大 corePoolSize。
2、 maximumPoolSize :当阻塞队列填满时,如果线程池中线程数没有超过最大线程数,则会创建新的
线程运行任务。否则根据拒绝策略处理新任务。非核心线程类似于临时借来的资源,这些线程在空闲时
间超过 keepAliveTime 之后,就应该退出,避免资源浪费。
3、 BlockingQueue :存储等待运行的任务。
4、 keepAliveTime :非核心线程空闲后,保持存活的时间,此参数只对非核心线程有效。设置为0,
表示多余的空闲线程会被立即终止。
5、 TimeUnit :时间单位
6、 ThreadFactory :每当线程池创建一个新的线程时,都是通过线程工厂方法来完成的。在
ThreadFactory 中只定义了一个方法 newThread,每当线程池需要创建新线程就会调用它。
7、 RejectedExecutionHandler :当队列和线程池都满了的时候,根据拒绝策略处理新任务。
4、拒绝策略有哪些
- AbortPolicy:默认的策略,直接抛出RejectedExecutionException
- DiscardPolicy:不处理,直接丢弃
- DiscardOldestPolicy:将等待队列队首的任务丢弃,并执行当前任务
- CallerRunsPolicy:由调用线程处理该任务