前言
一个在深圳从事开发五年的老友一个月前从原公司辞职后,昨天去腾讯总部面试Android高级岗,一面的时候,自我介绍后,陆陆续续问了很多问题,有着五年的从业经验很多项目开发的技术问题都回答的很通顺,面试官也很满意,就在最后以为自己要顺利通过时,【多线程——进程线程】,一个基础问题一时没有答上来就失去了二面的机会!
在我的身边不止发生了这一个大厂面试被拒的例子,所以从他们的身上我有总结出一个特点,无论是大厂BAT之类还是中厂,在面试过程中是逃不掉各类的开发基础问题,很多不注意的小细节正是打败我们的关键!走出自己的技术圈子,基础是必不可少的。
下面我分享一下我在TX官方群里收集的多线程面试专题,(更多大厂面试专题含答案文末一起分享)
1.什么是线程
线程就是进程中运行的多个子任务,是操作系统调用的最小单元
2.线程的状态
New:新建状态,new出来,还没有调用start
Runnable:可运行状态,调用start进入可运行状态,可能运行也可能没有运行,取决于操作系统的调度
Blocked:阻塞状态,被锁阻塞,暂时不活动,阻塞状态是线程阻塞在进入synchronized关键字修饰的方法或代码块(获取锁)时的状态。
Waiting:等待状态,不活动,不运行任何代码,等待线程调度器调度,wait sleep
Timed Waiting:超时等待,在指定时间自行返回
Terminated:终止状态,包括正常终止和异常终止
3.线程的创建
a.继承Thread重写run方法
b.实现Runnable重写run方法
c.实现Callable重写call方法
实现Callable和实现Runnable类似,但是功能更强大,具体表现在
a.可以在任务结束后提供一个返回值,Runnable不行
b.call方法可以抛出异常,Runnable的run方法不行
c.可以通过运行Callable得到的Fulture对象监听目标线程调用call方法的结果,得到返回值,(fulture.get(),调用后会阻塞,直到获取到返回值)
4.线程中断
一般情况下,线程不执行完任务不会退出,但是在有些场景下,我们需要手动控制线程中断结束任务,Java中有提供线程中断机制相关的Api,每个线程都一个状态位用于标识当前线程对象是否是中断状态
public boolean isInterrupted() //判断中断标识位是否是true,不会改变标识位public void interrupt() //将中断标识位设置为truepublic static boolean interrupted() //判断当前线程是否被中断,并且该方法调用结束的时候会清空中断标识位
需要注意的是interrupt()方法并不会真的中断线程,它只是将中断标识位设置为true,具体是否要中断由程序来判断,如下,只要线程中断标识位为false,也就是没有中断就一直执行线程方法
new Thread(new Runnable(){
while(!Thread.currentThread().isInterrupted()){
//执行线程方法
}
}).start();
前边我们提到了线程的六种状态,New Runnable Blocked Waiting Timed Waiting Terminated,那么在这六种状态下调用线程中断的代码会怎样呢,New和Terminated状态下,线程不会理会线程中断的请求,既不会设置标记位,在Runnable和Blocked状态下调用interrupt会将标志位设置位true,在Waiting和Timed Waiting状态下会发生InterruptedException异常,针对这个异常我们如何处理?
1.在catch语句中通过interrupt设置中断状态,因为发生中断异常时,中断标志位会被复位,我们需要重新将中断标志位设置为true,这样外界可以通过这个状态判断是否需要中断线程
try{
....
}catch(InterruptedException e){
Thread.currentThread().interrupt();
}
2.更好的做法是,不捕获异常,直接抛出给调用者处理,这样更灵活
5.Thread为什么不能用stop方法停止线程
从SUN的官方文档可以得知,调用Thread.stop()方法是不安全的,这是因为当调用Thread.stop()方法时,会发生下面两件事:
1.即刻抛出ThreadDeath异常,在线程的run()方法内,任何一点都有可能抛出ThreadDeath Error,包括在catch或finally语句中。
2.释放该线程所持有的所有的锁。调用thread.stop()后导致了该线程所持有的所有锁的突然释放,那么被保护数据就有可能呈现不一致性,其他线程在使用这些被破坏的数据时,有可能导致一些很奇怪的应用程序错误。
6.重入锁与条件对象,同步方法和同步代码块
7.volatile关键字
8.java内存模型
9.原子性 可见性 有序性
10.线程池ThreadPoolExecutor
11.线程池的种类
12.线程同步机制与原理,举例说明
13.arrayList与linkedList的读写时间复杂度
14.为什么HashMap线程不安全(hash碰撞与扩容导致)
15.进程线程的区别
16.Binder的内存拷贝过程
17.传统IPC机制的通信原理(2次内存拷贝)
18.Java内存模型(记住堆栈是内存分区,不是模型)
19.类的加载过程
20.什么情况下会触发类的初始化
21.双亲委托模式
22.双亲委托模式的好处
23.死锁的产生条件,如何避免死锁
24.App启动流程
25.Android单线程模型
26.RecyclerView在很多方面能取代ListView,Google为什么没把ListView划上一条过时的横线?
27.HashMap如何保证元素均匀分布
答案的篇幅过长,文中放进去不方便大家的阅读,还是以文档的形式看比较便于查看学习,有需要的朋友可以去加入那个腾讯的官方群,这里分享给大家点击链接加入群聊Android高级技术交流,里面不仅仅有Android各类专题面试资料,BAT高级源码面试题,还有提供学习的系统进阶视频资料,现在面对找工作的困境,需要提升自己的朋友们推荐加入。
最后
大家所认知的,给程序员定义的标签一定少不了“宅”这个字,那么 这个宅字我个人所理解的有两层意思,第一就是像很多人所想象的爱宅在家和编程代码过一辈子,第二种呢,就是盲目宅在自己的技术舒适区,眼界不宽,不能看到别人的长处,吸收别人的优点。虽然我不能得知这个宅字是不是真的能运用到所有人身上,但针对我这个老友,他,就是这样。