多线程面试题总结
新建、就绪、运行、阻塞、等待、超时等待、终止
最近面了三四家公司都有问到多线程的问题,所以今天在这里总结一下:
1.线程和进程的区别
②线程是操作系统调度的最小单元;
③一个程序至少有一个进程;一个进程至少有一个线程;
④同一进程的线程共享本进程的地址空间,而进程之间则是独立的地址空间。
2.为什么要用线程池
因为创建线程和关闭线程的行为是非常耗时的,会显著降低软件的性能表现。解决办法就是先创建n条线程,循环使用,从而节约了创建线程和关闭线程的时间开销。
3.线程池的参数以及意义(https://www.jianshu.com/p/06570447efed)
- corePoolSize:线程池核心线程数量
- maximumPoolSize:线程池最大线程数量
- keepAliverTime:当活跃线程数大于核心线程数时,空闲的多余线程最大存活时间
- unit:存活时间的单位
- workQueue:存放任务的队列
- handler:超出线程范围和队列容量的任务的处理程序(线程池饱和策略)
当提交一个新任务,线程池的处理流程如下:
判断线程池中核心线程数是否已达阈值corePoolSize,若否,则创建一个新核心线程执行任务
若核心线程数已达阈值corePoolSize,判断阻塞队列workQueue是否已满,若未满,则将新任务添加进阻塞队列
若满,再判断,线程池中线程数是否达到阈值maximumPoolSize,若否,则新建一个非核心线程执行任务。若达到阈值,则执行线程池饱和策略。
线程池饱和策略分为一下几种:
AbortPolicy:直接抛出一个异常,默认策略
DiscardPolicy: 直接丢弃任务
DiscardOldestPolicy:抛弃下一个将要被执行的任务(最旧任务)
CallerRunsPolicy:主线程中执行任务
4.创建线程的办法和创建线程池的办法
创建线程的办法
①继承一个Thread类
② 实现Runnable接口
③ 匿名内部类
创建线程池的办法
newCachedThreadPool创建一个可缓存线程池,如果线程池长度超过处理需要,可灵活回收空闲线程,若无可回收,则新建线程。
newFixedThreadPool 创建一个定长线程池,可控制线程最大并发数,超出的线程会在队列中等待。
newScheduledThreadPool 创建一个定长线程池,支持定时及周期性任务执行。
newSingleThreadExecutor 创建一个单线程化的线程池,它只会用唯一的工作线程来执行任务,保证所有任务按照指定顺序(FIFO, LIFO, 优先级)执行。
5.线程中run和start的区别
调用start方法方可启动线程,而run方法只是thread类中的一个普通方法调用,还是在主线程里执行。
通过调用Thread类的 start()方法来启动一个线程,这时此线程处于就绪(可运行)状态,并没有运行,一旦得到cpu时间片,就开始执行run()方法
6.sleep和wait的区别
首先sleep和wait之间没有任何关系
sleep是Thread类的方法,指的是当前线程暂停。
wait是Object类的方法, 指的占用当前对象的线程临时释放对当前对象的占用,以使得其他线程有机会占用当前对象。 所以调用wait方法一定是在synchronized 中进行
7.sleep和yeild的区别
① sleep()方法给其他线程运行机会时不考虑线程的优先级,因此会给低优先级的线程以运行的机会;yield()方法只会给相同优先级或更高优先级的线程以运行的机会;
② 线程执行sleep()方法后转入阻塞(blocked)状态,而执行yield()方法后转入就绪(ready)状态;
③ sleep()方法声明抛出InterruptedException,而yield()方法没有声明任何异常;
④ sleep()方法比yield()方法(跟操作系统CPU调度相关)具有更好的可移植性。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· C#/.NET/.NET Core优秀项目和框架2025年2月简报
· Manus爆火,是硬核还是营销?
· 一文读懂知识蒸馏
· 终于写完轮子一部分:tcp代理 了,记录一下