移动开发最新HandlerThread源码分析,2024年最新附Android面经

面试复习路线,梳理知识,提升储备

自己的知识准备得怎么样,这直接决定了你能否顺利通过一面和二面,所以在面试前来一个知识梳理,看需不需要提升自己的知识储备是很有必要的。

关于知识梳理,这里再分享一下我面试这段时间的复习路线:(以下体系的复习资料是我从各路大佬收集整理好的)

  • 架构师筑基必备技能
  • Android高级UI与FrameWork源码
  • 360°全方面性能调优
  • 解读开源框架设计思想
  • NDK模块开发
  • 微信小程序
  • Hybrid 开发与Flutter

知识梳理完之后,就需要进行查漏补缺,所以针对这些知识点,我手头上也准备了不少的电子书和笔记,这些笔记将各个知识点进行了完美的总结:

Android开发七大模块核心知识笔记

《960全网最全Android开发笔记》

《379页Android开发面试宝典》

历时半年,我们整理了这份市面上最全面的安卓面试题解析大全
包含了腾讯、百度、小米、阿里、乐视、美团、58、猎豹、360、新浪、搜狐等一线互联网公司面试被问到的题目。熟悉本文中列出的知识点会大大增加通过前两轮技术面试的几率。

如何使用它?

1.可以通过目录索引直接翻看需要的知识点,查漏补缺。
2.五角星数表示面试问到的频率,代表重要推荐指数

《507页Android开发相关源码解析》

只要是程序员,不管是Java还是Android,如果不去阅读源码,只看API文档,那就只是停留于皮毛,这对我们知识体系的建立和完备以及实战技术的提升都是不利的。

真正最能锻炼能力的便是直接去阅读源码,不仅限于阅读各大系统源码,还包括各种优秀的开源库。

网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。

需要这份系统化学习资料的朋友,可以戳这里获取

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!

*/

protected void onLooperPrepared() {

}

@Override

public void run() {

mTid = Process.myTid();

Looper.prepare();

//持有锁机制来获得当前线程的Looper对象

synchronized (this) {

mLooper = Looper.myLooper();

//发出通知,当前线程已经创建mLooper对象成功,这里主要是通知getLooper方法中的wait

notifyAll();

}

//设置线程的优先级别

Process.setThreadPriority(mPriority);

//这里默认是空方法的实现,我们可以重写这个方法来做一些线程开始之前的准备,方便扩展

onLooperPrepared();

Looper.loop();

mTid = -1;

}

public Looper getLooper() {

if (!isAlive()) {

return null;

}

// 直到线程创建完Looper之后才能获得Looper对象,Looper未创建成功,阻塞

synchronized (this) {

while (isAlive() && mLooper == null) {

try {

wait();

} catch (InterruptedException e) {

}

}

}

return mLooper;

}

public boolean quit() {

Looper looper = getLooper();

if (looper != null) {

looper.quit();

return true;

}

return false;

}

public boolean quitSafely() {

Looper looper = getLooper();

if (looper != null) {

looper.quitSafely();

return true;

}

return false;

}

/**

  • Returns the identifier of this thread. See Process.myTid().

*/

public int getThreadId() {

return mTid;

}

}

1)首先我们先来看一下它的构造方法

public HandlerThread(String name) {

super(name);

mPriority = Process.THREAD_PRIORITY_DEFAULT;

}

public HandlerThread(String name, int priority) {

super(name);

mPriority = priority;

}

有两个构造方法,一个参数的和两个参数的,name代表当前线程的名称,priority为线程的优先级别

2)接着我们来看一下run()方法,在run方法里面我们可以看到我们会初始化一个Looper,并设置线程的优先级别

public void run() {

mTid = Process.myTid();

Looper.prepare();

//持有锁机制来获得当前线程的Looper对象

synchronized (this) {

mLooper = Looper.myLooper();

//发出通知,当前线程已经创建mLooper对象成功,这里主要是通知getLooper方法中的wait

notifyAll();

}

//设置线程的优先级别

Process.setThreadPriority(mPriority);

//这里默认是空方法的实现,我们可以重写这个方法来做一些线程开始之前的准备,方便扩展

onLooperPrepared();

Looper.loop();

mTid = -1;

}

  • 还记得我们前面我们说到使用HandlerThread的时候必须笑调用start()方法,接着才可以将我们的HandlerThread和我们的handler绑定在一起吗?其实原因就是我们是在run()方法才开始初始化我们的looper,而我们调用HandlerThread的start()方法的时候,线程会交给虚拟机调度,由虚拟机自动调用run方法

mHandlerThread.start();

mThreadHandler = new Handler(mHandlerThread.getLooper()) {

@Override

public void handleMessage(Message msg) {

checkForUpdate();

if(isUpdate){

mThreadHandler.sendEmptyMessage(MSG_UPDATE_INFO);

}

}

};

  • 这里我们为什么要使用锁机制和notifyAll();,原因我们可以从getLooper()方法中知道

public Looper getLooper() {

if (!isAlive()) {

return null;

}

// 直到线程创建完Looper之后才能获得Looper对象,Looper未创建成功,阻塞

synchronized (this) {

while (isAlive() && mLooper == null) {

try {

wait();

} catch (InterruptedException e) {

}

}

}

return mLooper;

}

总结:在获得mLooper对象的时候存在一个同步的问题,只有当线程创建成功并且Looper对象也创建成功之后才能获得mLooper的值。这里等待方法wait和run方法中的notifyAll方法共同完成同步问题。

3)接着我们来看一下quit方法和quitSafe方法

//调用这个方法退出Looper消息循环,及退出线程

public boolean quit() {

Looper looper = getLooper();

if (looper != null) {

looper.quit();

return true;

}

return false;

}

//调用这个方法安全地退出线程

@TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR2)

public boolean quitSafely() {

Looper looper = getLooper();

if (looper != null) {

looper.quitSafely();

return true;

}

return false;

}

跟踪这两个方法容易知道只两个方法最终都会调用MessageQueue的queue(boolean safe)方法

void quit(boolean safe) {

if (!mQuitAllowed) {

throw new IllegalStateException(“Main thread not allowed to quit.”);

}

synchronized (this) {

if (mQuitting) {

return;

}

mQuitting = true;

//安全退出调用这个方法

if (safe) {

removeAllFutureMessagesLocked();

} else {//不安全退出调用这个方法

removeAllMessagesLocked();

}

// We can assume mPtr != 0 because mQuitting was previously false.

nativeWake(mPtr);

}

}

不安全的会调用removeAllMessagesLocked();这个方法,我们来看这个方法是怎样处理的,其实就是遍历Message链表,移除所有信息的回调,并重置为null

private void removeAllMessagesLocked() {

Message p = mMessages;

while (p != null) {

Message n = p.next;

p.recycleUnchecked();

p = n;

}

mMessages = null;

}

安全地会调用removeAllFutureMessagesLocked();这个方法,它会根据Message.when这个属性,判断我们当前消息队列是否正在处理消息,没有正在处理消息的话,直接移除所有回调,正在处理的话,等待该消息处理处理完毕再退出该循环。因此说quitSafe()是安全的,而quit()方法是不安全的,因为quit方法不管是否正在处理消息,直接移除所有回调。

private void removeAllFutureMessagesLocked() {

final long now = SystemClock.uptimeMillis();

Message p = mMessages;

if (p != null) {

//判断当前队列中的消息是否正在处理这个消息,》没有的话,直接移除所有回调

if (p.when > now) {

removeAllMessagesLocked();

} else {//正在处理的话,等待该消息处理处理完毕再退出该循环

Message n;

for (;😉 {

n = p.next;

if (n == null) {

return;

}

if (n.when > now) {

break;

}

p = n;

}

p.next = null;

do {

p = n;

n = p.next;

p.recycleUnchecked();

} while (n != null);

}

}

}

到此HandlerThread源码分析为止


  1. 关于IntentService的,可以参考我的这一篇博客IntentService使用及源码分析

  2. 关于Handler消息机制的,可以参考郭林大神的这篇博客Android异步消息处理机制完全解析,带你从源码的角度彻底理解

题外话

最近在准备校招,比较忙,不过个人整理了一些常见的算法题目,有空的话我会把它分享出来,一起加油,Come on!

简书博客博客地址:
转载请注明原博客地址:
例子源码下载地址:

最后

Android学习是一条漫长的道路,我们要学习的东西不仅仅只有表面的 技术,还要深入底层,弄明白下面的 原理,只有这样,我们才能够提高自己的竞争力,在当今这个竞争激烈的世界里立足。

人生不可能一帆风顺,有高峰自然有低谷,要相信,那些打不倒我们的,终将使我们更强大,要做自己的摆渡人。

资源持续更新中,欢迎大家一起学习和探讨。

网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。

需要这份系统化学习资料的朋友,可以戳这里获取

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!

源码的角度彻底理解]( )

题外话

最近在准备校招,比较忙,不过个人整理了一些常见的算法题目,有空的话我会把它分享出来,一起加油,Come on!

简书博客博客地址:
转载请注明原博客地址:
例子源码下载地址:

最后

Android学习是一条漫长的道路,我们要学习的东西不仅仅只有表面的 技术,还要深入底层,弄明白下面的 原理,只有这样,我们才能够提高自己的竞争力,在当今这个竞争激烈的世界里立足。

人生不可能一帆风顺,有高峰自然有低谷,要相信,那些打不倒我们的,终将使我们更强大,要做自己的摆渡人。

资源持续更新中,欢迎大家一起学习和探讨。

网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。

需要这份系统化学习资料的朋友,可以戳这里获取

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值