线程间通信原理
首先我们先来看一下线程间通信原理的流程图:
线程间通信原理:
1.Android是单线程模型,单线程的好处是避免代码重复和效率低。
2.主线程负责更新UI,工作线程不能更新UI。
3.工作线程执行耗时操作,避免主线程堵塞。
4.主线程通过Looper遍历消息队列,有消息处理,没消息休息。
Message类:
用于存放线程间通信所需的消息,包括代码。重要的属性包括:
target属性: 存放收发该消息的Handler对象
callback属性: 存放Runnabule对象
what属性: int类型,表示消息的类型,用于区分不同类型的消息
arg1属性: 存放消息中类型是int数据
arg2属性: 存放消息中类型是int数据
obj属性: Object类型,存放消息中任意类型的数据
data属性: Bundle类型,存放任意类型的数据
Handler类:
Android通过Handler类实现线程间收发消息。Handler原意是“操作者”。Android是单线程模型,只有主线程才能更新UI,工作线程更新UI需要用Handler将数据发送给主线程来更新UI。Handler负责在其它线程发送消息,同时在本线程接受处理消息。线程和Handler是一对多的关系,一个线程可以对应多个Handler,但一个Handler只能为一个线程服务。
关于Handler类的构造器:
无参构造器:
创建为当前线程工作的Handler对象,并实现HandlerMessage方法
public Handler(Callback callback){
this (callback,false);
}
创建与指定Looper绑定的Handler对象
public Handler(Looper looper){
this(looper,null,false);
}
创建与指定Looper绑定的Handler对象,并实现HandlerMessage方法
public Handler(Looper looper,Callback callback){
this(Looper,callback,false);
}
Handler发送消息:
post方法发送一段代码
post源码:
getPostMessage方法源码:
sendMessageDelayed方法源码:
sendMessageAtTime方法源码:
sendMessage方法源码:
Handller处理消息:
Handler类通过dispatchMessage方法将消息队列中取出的消息分发给相关方法处理。
dispatchMessage方法分发消息的流程:
dispatchMessage方法源码:
handleCallback方法源码:
关于Callback接口:它是Handler类的内部接口,在Message.callback中使用。
Callback接口源码:
为什么我们要用Callback接口?Handler有一个带有Callback的构造方法,通过该方法创建Handller对象,可以避免创建Handler的子类时,复写handleMessage。执行Handler.mCallback.handleMessage方法,就可使用Callback接口。
Looper类:
Looper是实现Android线程间通信重要的一个类,Android为主线程自动创建一个Looper。Looper用于为指定线程创建并维护一个消息队列,用先进先出的方式从消息队列中取出消息,交给Handler处理。工作线程默认没有Looper和消息循环,一个线程只能有一个Looper。
Looper的创建:
Looper由Looper.prepare方法创建,不能直接new。
public static void prepare(){
prepare(true);
}
ThreadLocal允许每个线程都创建一份自己的局部变量。ThreadLocall是泛型类,sThreadLocal用于为每个线程保存一个Looper对象。ThreadLocal通过set方法将与当前线程相关联的LLooper对象保存在ThreadLocal(Map集合中)。ThreadLocal通过get方法将与当前线程相关联的Looper对象中ThreadLocal(Map集合中)取出。
quiteAllowed:
为主线程创建Looper的prepareMainLooper方法。
工作线程在创建时,必须设置quietAllowed为true,允许Looper.quit结束Looper对消息队列的遍历。但主线程的Looper在创建时,quitAllowed必须设置为false,即不允许主线程中的Looper退出。
遍历消息队列:
Looper.loop方法用于遍历消息队列。(源码就不贴出来了)
常见方法:
Looper.myLooper(),得到当前线程的looper对象。
getThread(),得到looper对象所属线程。
quit(),结束looper循环,主线程不能调用本方法。
MessageQueue类:
是一个低等级的持有Messages集合的类,被ooper分发,Message会发送到与Hanlder所绑定的MessageQueue中通过Looper.myQueue()方法来检索当前线程的MessageQueue。(数据结构是先进先出的队列)。
常用方法:
enqueueMessage方法:将Message入队列。用于链表实现队列,并用无限循环遍历队列中的消息。
next方法:从队列中取出Message。next用无限循环遍历消息队列,取出消息。
Android中HandlerThread类和AsyncTask类封装了消息循环机制。
handler通信机制中的 Looper.loop方法中调用queue.next()实现阻塞的原理?
主线程大多数时候都是处于休眠状态,并不会消耗大量CPU资源。
Handler机制是使用pipe(Linux中的管道)来实现的,没有消息处理时主线程会在管道的读端阻塞;
有消息时,Binder线程往主线程消息队列里添加消息,然后会往管道写端写一个字节,以此来唤醒主线程从管道读端返回, 也就是说queue.next()会调用返回。
Handler机制是使用pipe(Linux中的管道)来实现的,没有消息处理时主线程会在管道的读端阻塞;
有消息时,Binder线程往主线程消息队列里添加消息,然后会往管道写端写一个字节,以此来唤醒主线程从管道读端返回, 也就是说queue.next()会调用返回。