Android并发编程高级面试题汇总最全最细面试题讲解持续更新中👊👊 👀你想要的面试题这里都有👀 👇👇👇
线程池管理线程原理
这道题想考察什么?
是否了解线程池相关的理论知识
考察的知识点
- 线程中的基本概念,线程的生命周期
- 线程池的原理
- 常见的几种线程池的特点以及各自的应用场景
考生应该如何回答
在一个应用程序中,我们需要多次使用线程,也就意味着,我们需要多次创建并销毁线程。而创建并销毁线程的过程势必会消耗内存。而在Java中,内存资源是及其宝贵的,所以,我们就提出了线程池的概念。线程池的好处,就是可以方便的管理线程,也可以减少内存的消耗。
线程池的创建
public ThreadPoolExecutor(int corePoolSize,
int maximumPoolSize,
long keepAliveTime,
TimeUnit unit,
BlockingQueue<Runnable> workQueue,
ThreadFactory threadFactory,
RejectedExecutionHandler handler)
- corePoolSize :核心线程数量,默认情况下,线程池会一直维护corePoolSize个线程,让这些线程不会被回收。
- maximumPoolSize:线程池最大线程的数量;
- keepAliveTime:线程的最长闲置时间,若线程闲置超过此时间则回收;
- util:闲置时间单位;
- workQueue:等待队列,当线程池中执行的任务超过核心线程数后,新提交任务将加入此队列等待执行;
- threadFactory:创建线程的线程工厂
- handler:拒绝策略,在任务满了之后,如何处理继续添加的任务。
线程池的执行流程
在新建的线程池中,默认最开始里面是没有线程的。当然,可以使用prestartAllCoreThreads
方法,来提前把corePoolSize的核心线程。
向线程池中提交任务时,首先判断线程池中正在执行的线程数是否已经达到核心线程数:
- 未达到:创建新线程执行任务
- 达到:将任务添加进入任务队列
在向任务队列添加任务时,可能添加成功,也可能添加失败:
- 成功:等待其他线程执行完成,将会自动从队列中获取任务继续执行;
- 失败:判断当前线程池线程数是否达到最大线程数
若添加队列失败,在判断是否达到最大线程数是也可能存在两种结果:
- 达到:回调
RejectedExecutionHandler
拒绝策略,JDK提供了四种拒绝策略处理类:AbortPolicy(抛出一个异常,默认的),DiscardPolicy(直接丢弃任务),DiscardOldestPolicy(丢弃队列里最老的任务,将当前这个任务继续提交给线程池),CallerRunsPolicy(交给线程池调用所在的线程进行处理) - 未达到:创建新线程执行任务
核心线程
默认情况下,线程池会一直维护核心线程,使其不被回收。
可以使用
allowCoreThreadTimeOut(true)
设置核心线程也会被闲置回收。
线程池运行线程执行任务:
while (task != null || (task = getTask()) != null) {
//......
task.run();
}
其中getTask
则会从队列中获取待执行任务,不断执行。如果当前队列中没有待执行任务,非核心线程会等待指定的keepAliveTime时间到达后正常退出线程,而核心线程会通过任务队列的take
方法阻塞,从而保证其持续运行。
Runnable r = timed ?
//非核心线程
workQueue.poll(keepAliveTime, TimeUnit.NANOSECONDS) :
//核心线程
workQueue.take();
线程池有几种实现方式,线程池的七大参数有哪些? (美团)
这道题想考察什么?
是否了解线程池的七大参数有哪些与真实场景使用,是否熟悉线程池的七大参数有哪些
考察的知识点
线程池的七大参数有哪些的概念在项目中使用与基本知识
考生应该如何回答
七大参数
- corePoolSize
线程池中的常驻核心线程数 - maximumPoolSize
线程池能够容纳同时执行的最大线程数,此值必须大于等于1 - keepAliveTime
空闲线程的存活时间。 - unit
keepAliveTime的单位 - workQueue
任务队列,被提交但尚未被执行的任务 - threadFactory
表示生成线程池中工作线程的线程工厂,用于创建线程一般默认即可 - handler:
拒绝策略,表示当队列满了并且工作线程大于等于线程池最大线程数(maximumPoolSize)时如何处理
实现方式
使用JDK中自带的线程池可以通过创建ThreadPoolExecutor线程池对象,也能够通过Executors中定义的静态方法。其中Executors静态方法创建的线程池主要有以下类型:
1.newSingleThreadExecutor
创建只有一个线程的线程池,且线程的存活时间是无限的;当该线程正繁忙时,对于新任务会进入阻塞队列中(无界的阻塞队列)
适用:一个任务一个任务执行的场景
2.newCachedThreadPool
当有新任务到来,则插入到SynchronousQueue中,由于SynchronousQueue是同步队列,因此会在池中寻找可用线程来执行,若有可以线程则执行,若没有可用线程则创建一个线程来执行该任务;若池中线程空闲时间超过指定大小,则该线程会被销毁。
适用:执行很多短期异步的场景
3.newFixedThreadPool
创建可容纳固定数量线程的池子,每隔线程的存活时间是无限的,当池子满了就不在添加线程了;如果池中的所有线程均在繁忙状态,对于新任务会进入阻塞队列中(无界的阻塞队列),但是,在线程池空闲时,即线程池中没有可运行任务时,它不会释放工作线程,还会占用一定的系统资源。
适用:长期执行的场景
4.NewScheduledThreadPool
创建一个固定大小的线程池,线程池内线程存活时间无限制,线程池可以支持定时及周期性任务执行,如果所有线程均处于繁忙状态,对于新任务会进入DelayedWorkQueue队列中,这是一种按照超时时间排序的队列结构
适用:周期性执行的场景