Android面试原理(Handler)

  • Handler机制和底层实现

MessageQueue 用来存放线程消息

Handler 与Looper沟通

Looper 一个线程可以产生一个Looper对象,对消息进行循环

Message 线程消息的载体

ActivityThread --> main() 函数Looper.prepareMainLooper()就是制造出一个looper

sMainThreadHandler = thread.getHandler();

Looper.loop(),启动,让它开始循环

 

1.Looper me = myLooper();

2.MessageQueue queue = me.mQueue;

3.Message msg = queue.next();

4.msg.target.dispatchMessage(msg)

 

looper就是一个消息处理中心,它负责管理消息队列,负责让消息发出去,msg.target.dispatchMessage(msg)

 

mCallback.handleMessage(msg)

sThreadLocal.set(new Looper());

 

 Looper --> prepare() --> sThreadLocal.set(new Looper()) 设置了looper

 

MessageQueue的底层实现是利用管道和epoll机制来实现的

文件描述符

是内核为了高效管理已被打开的文件所创建的索引,是一个非负整数(通常是小整数),用于指代被打开的文件,所有执行I/O操作的系统调用都通过文件描述符

pipe

管道,使用I/O流操作,Linux 系统中的一种进程间通信机制。简单来说,管道就是一个文件,在管道的两端,分别是两个打开文件的文件描述符。这两个打开文件描述符都是对应同一个文件,其中一个是用来读的,别一个是用来写的,一般的使用方式就是,一个线程通过读文件描述符中来读管道的内容。当管道没有内容时,这个线程就会进入等待状态,而另外一个线程通过写文件描述符来向管道中写入内容。写入内容的时候,如果另一端正有线程正在等待管道中的内容,那么这个线程就会被唤醒

epoll

IO多路复用机制,可以理解为event poll,不同于忙轮询和无差别轮询,可以同时监控多个描述符,当某个描述符就绪(读或写就绪),则立刻通知相应程序进行读或写操作)

机制
线程在进入循环之前,会在 JNI 创建管道,当消息队列为空时,线程处于空闲等待状态。通过 epoll 机制监听 EPOLLIN 事件,当有新事件进入消息队列时,并且当前线程处于空闲状态,通过向管道写入数据,来唤醒线程

  • Handler、Thread和HandlerThread的差别

Handler

在Android中负责发送和处理消息,通过它可以实现线程间通信

Thread

Java中进程执行运算的最小单位,资源调度基本单位

HandlerThread

一个继承Thread的类,进行了便利封装

HandlerThread对象start后可以获得其Looper对象,并且使用这个Looper对象实例Handler,之后Handler就可以运行在其他线程中了。

  • Handler发消息给子线程,Looper怎么启动

主线程自动创建好了Looper,但是子线程需要自己创建Looper

            Looper.prepare();

            mHandler = new Handler();      

            Looper.loop();

 

初始化Looper 绑定Handler到子线程的Looper对象 开始启动Looper

最后在主线程绑定过的Handler发消息到子线程

  • 在任何地方new Handler都是什么线程下

不传递 Looper 创建 Handler

Handler handler = new Handler();

不传递 Looper 对象的情况下,在哪个线程创建 Handler 默认获取的就是该线程的 Looper 对象,那么 Handler 的一系列操作都是在该线程进行的。

传递 Looper 创建 Handler

传递 Looper对象 Handler 就直接使用了。所以对于传递 Looper 对象创建 Handler 的情况下,传递的 Looper 是哪个线程的,Handler 绑定的就是该线程

  • ThreadLocal原理,实现及如何保证Local属性

线程局部变量

ThreadLocal诞生的目的是隔离不同线程所使用的变量

ThreadLocal可以用来把实例变量共享成全局变量,让程序中所有的方法都可以访问到该变量。由于存到ThreadLocal的变量都是当前线程本身,其他线程无法访问,存到ThreadLocal中只是为了方便在程序中同一个线程之间传递这个变量(和解决线程安全没有关系)

  • 请解释下在单线程模型中Message、Handler、Message Queue、Looper之间的关系

Handler

用来发送消息,创建时先获取默认或传递来的 Looper 对象,并持有 Looper 对象包含的 MessageQueue发送消息时使用该 MessageQueue 对象来插入消息并把自己封装到具体的 Message 中

Looper

用来为某个线程作消息循环。Looper 持有一个 MessageQueue 对象 mQueue,这样就可以通过循环来获取 MessageQueue 所维护的 Message。如果获取的 MessageQueue 没有消息时,便阻塞在 loop 的queue.next() 中的 nativePollOnce() 方法里,反之则唤醒主线程继续工作,之后便使用 Message 封装的 handler 对象进行处理

MessageQueue

是一个消息队列,它不直接添加消息,而是通过与 Looper 关联的 Handler 对象来添加消息

Message

包含了要传递的数据和信息

 

你可能感兴趣的:(Android)