一、线程池相关面试题
1.为什么使用线程池?
谈谈什么是线程池?线程池和数据库连接池相似,可以统一管理和维护线程,减少没必要的开销。
因为频繁的开启或停止线程,线程需要重新被CPU从就绪状态到运行状态调度,发生CPU上下文切换,效率非常低。
核心是复用机制。
提前创建好一些固定的线程数一直在运行状态,实现复用 从而可以减少就绪状态到运行状态的切换。
2.项目中哪些地方使用到了多线程?
项目中有使用SpringBoot整合线程池去异步的发送短信?因为只使用new的方式去创建线程不好管理我们的线程,会有安全隐患。由于我们项目比较小所以使用线程池去异步的发送短信,如果项目数据量大应该使用消息队列MQ去做异步。
3.线程池有哪些作用?
1.减少资源消耗:提前创建一些固定的线程,减少线程频繁的创建和销毁
2.提高响应效率:线程创建好之后处于运行状态,请求可以马上执行。
3.提高线程的可管理性:现成是稀缺资源,如果无限创建,不仅会消耗系统资源,还会因为线程分布不合理导致资源调度失衡,降低系统稳定性。使用线程池可以进行统一的调度,分配,调优,管理。
4.提供更强大的功能:线程池具备可拓展性,如延时定时线程池ScheduledThreadPoolExecutor。
4.线程池创建的方式
- Executors.newCachedThreadPool() 可缓存线程池
- Executors.newFixedThreadPool() 可定长度 限制最大线程数
- Executors.newScheduledThreadPool() 可定时线程池
- Executors.newSingleThreadPool() 单例
底层都是基于ThreadPoolExcutor构造函数进行封装,非常遗憾,在阿里巴巴开发手册中不建议使用JDK自带的线程池创建工具创建我们的线程,底层是使用无界的队列缓存我们的线程,有可能发生我们的线程池溢出问题。
5.线程池底层实现原理
核心点:复用机制
1.提前创建好固定的线程一直在运行状态------使用死循环实现
2.提交的任务缓存到一个并发的工作队列集合中,交给正在运行的线程执行
3.正在运行的线程从工作队列中获取任务并执行。
4.工作队列满之后就走拒绝策略。
6.线程池核心参数有哪些
1.核心线程数:corePoolSize 一直保持运行的线程
2.最大线程数:maximuPoolSize 线程池允许创建的最大线程数
3.非核心线程存活时间:keepAliveTime
4.任务队列:workQueue 保存执行的任务
5.内部创建线程工厂: threadFactory
6.任务执行失败策略:handler
7.线程池创建的线程会一直在运行状态吗?
不会,非核心线程数在不被使用时会被销毁。
线程相关面试题
1.什么是悲观锁?什么是乐观锁?
悲观锁:
1.站在MySQL的角度上,悲观锁就是比较悲观的,当多个线程对同时同一行数据进行修改操作的时候,只能有一个线程获取到数据行锁,对数据修改成功(InnoDB引擎默认数据行锁),其他线程则进入阻塞状态。
2.站在Java层面上,如果没有获取到锁,则会进入阻塞状态,唤醒锁的成本非常的高,从新被我们CPU从就绪调度为运行状态
乐观锁:
认为共享资源每次访问的时候都不会出现问题,线程无需进入阻塞状态,一直在运行, 无需加锁,只是在提交之前去校验一下数据是否被其他线程修改了。
2.Java的锁分类有哪些?
1.悲观锁和乐观锁
2.公平锁和非公平锁
3.自旋锁和重入锁
4.重量级锁和轻量级锁
5.独占锁和
公平锁和非公平锁
公平锁底层基于链表实现,先请求锁的先获得锁,非公平锁谁请求到锁就谁获得锁。
3.谈谈你对ThreadLocal的理解
ThreadLocal是线程缓存局部属性,线程安全的容器,底层封装了ThreadLocalMap集合,每个线程都有自己对应的Map集合。
4.学好AQS 就能学好Java的并发包
1.死锁发生的四大条件
1.互斥条件:同一时间只能一个线程使用资源
2.不可剥夺条件:一个线程已经获得资源,在未释放之前都不会被其他线程抢占
3.请求和保持条件:现成在等待的过程中,不会释放已经抢占的资源
4.循环等待条件:多个线程相互等待对方释放资源
(我的总结是:围绕资源展开,同一个时间上资源只能一个线程拥有)
2.多线程的创建方式
1.实现Runnable接口,实现run方法,方法没有返回值,无法抛出异常。
2.实现Callable接口,实现call方法,方法有返回值,可以抛出异常。
3.继承Thread类,重写run方法,需要调用start方法开启线程(也是启动线程的唯一方法)。
4.创建线程池,使用Executor框架接口的实现创建线程池,和Excutors工具类创建线程池
3.线程、进程的区别
进程:是操作系统分配资源基本单元,有独立的内存空间,由多个线程组成
线程:现成是操作系统调度的最小单元,拥有自己的栈和共享堆