本文已参与「新人创作礼」活动,一起开启掘金创作之路。
Handler中员工一览
Handler、Looper、Message、MessageQueue、Thread、ThreadLocal、ThreadLocalMap
ThreadLocal
ThreadLocal提供管理线程内部变量副本功能。以作为key存储在ThreadLocalMap中
主要方法:
get():获取当前线程里的threadLocalMap,获取存在该map中此ThreadLocal对应的value
即:获取当前线程中某一变量副本
set():获取当前线程中的threadLocalMap,传入this和value,存入threadLocalMap
即:存入当前线程的某一变量副本
源码如下:
class ThreadLocal {
protected T initialValue() {
return null;
}
ThreadLocalMap getMap(Thread t) {
//获取目标线程中的ThreadLocalMap
return t.threadLocals;
}
public T get() {
// 获取当前线程中的ThreadLocalMap
Thread t = Thread.currentThread();
ThreadLocalMap map = getMap(t);
if (map != null) {
ThreadLocalMap.Entry e = map.getEntry(this);
if (e != null) {
//获取此ThreadLocal对应的value
@SuppressWarnings("unchecked")
T result = (T)e.value;
return result;
}
}
//如果目标线程中ThreadLocalMap为null或
// 此ThreadLocal未作为Key存入目标Map,
// 进行初始化并返回null
return setInitialValue();
}
private T setInitialValue() {
//value为null
T value = initialValue();
Thread t = Thread.currentThread();
ThreadLocalMap map = getMap(t);
//初始化并将此key存入map,映射值为null
if (map != null)
map.set(this, value);
else
createMap(t, value);
return value;
}
public void set(T value) {
//获取当前线程的ThreadLocalMap
Thread t = Thread.currentThread();
ThreadLocalMap map = getMap(t);
//将此ThreadLocal和对应的value存入map
if (map != null)
map.set(this, value);
else
createMap(t, value);
}
//初始化目标线程中的ThreadLocalmap
void createMap(Thread t, T firstValue) {
t.threadLocals = new ThreadLocalMap(this, firstValue);
}
}
ThreadLocalMap
ThreadLocalMap是ThreadLocal的静态内部类,被Thread持有,管理线程内部变量副本功能。 内部持有ThreadLocal作为key,object作为value。
具体实现为:
定义内部类Entry(ThreadLocal, Object),存储映射关系,并且继承WeakReference
定义Entry[]类型table,持有映射数组
set() 和 getEntry() 存入 取出映射关系和value
源码如下:
static class ThreadLocalMap {
static class Entry extends WeakReference> {
Object value;
Entry(java.lang.ThreadLocal k, Object v) {
super(k);
value = v;
}
}
//数组存储Entry
private Entry[] table;
//tab中获取key对应的Entry
private Entry getEntry(java.lang.ThreadLocal key) {
int i = key.threadLocalHashCode & (table.length - 1);
Entry e = table[i];
if (e != null && e.refersTo(key))
return e;
else
return getEntryAfterMiss(key, i, e);
}
//使用传入的key和value生成一个Entry存入tab中
private void set(java.lang.ThreadLocal key, Object value) {
Entry[] tab = table;
int len = tab.length;
int i = key.threadLocalHashCode & (len-1);
for (Entry e = tab[i];
e != null;
e = tab[i = nextIndex(i, len)]) {
java.lang.ThreadLocal k = e.get();
if (k == key) {
e.value = value;
return;
}
if (k == null) {
replaceStaleEntry(key, value, i);
return;
}
}
tab[i] = new Entry(key, value);
int sz = ++size;
if (!cleanSomeSlots(i, sz) && sz >= threshold)
rehash();
}
}
Thread
Thread线程。持有ThreadLocalMap、当前线程中唯一Looper存在变量threadLocalMap中。
class Thread implements Runnable {
//默认为null,ThreadLocal中createMap方法为其赋值
ThreadLocal.ThreadLocalMap threadLocals = null;
}
Looper
轮训消息队列,消息派发功能。被Thread持有。
内部定义静态常量ThreadLocal,以此常量作为key存在thread内部变量threadLocalMap中,保证一个线程内部只有一个looper
主要实现:
持有并初始化MessageQueue
构造方法私有 只可通过prepare()方法进行初始化
prepare():通过threadLocal.get()方法判断当前线程是否已持有Looper,若持有则抛出运行时异常RuntimeException(),否则则new出looper并调用threadLocal.set()存入当前线程
loop():循环访问MessageQueue.next()方法,在获取到null之前不退出循环,以此不停分发消息队列中新的消息;获取到Message之后,调用Message中Handlel类型的target中dispatchMessage()分发到目标Handler进行消息处理。
quit(): 调用MessageQueue中的quit,进行退出和资源释放
public final class Looper {
//定义静态常量ThreadLocal做key,key唯一,则当前线程中只能存入唯一looper
//会以sThreadLocal作为key,此looper(this)作为value存入Thread中ThreadLocalMap
static final ThreadLocal sThreadLocal = new ThreadLocal();
//消息队列
final MessageQueue mQueue;
//所在线程
final Thread mThread;
//静态方法,用于loop初始化
public static void prepare() {
prepare(true);
}
//校验此looper是否已存在于当前线程
private static void prepare(boolean quitAllowed) {
//存在则抛出异常
if (sThreadLocal.get() != null) {
throw new RuntimeException("Only one Looper may be created per thread");
}
//否则进行初始化并存入当前线程的ThreadLocalMap
sThreadLocal.set(new Looper(quitAllowed));
}
//私有构造,保证安全
private Looper(boolean quitAllowed) {
mQueue = new MessageQueue(quitAllowed);
mThread = Thread.currentThread();
}
//获取当前线程中looper
public static @Nullable Looper myLooper() {
return sThreadLocal.get();
}
//保留主要代码
public static void loop() {
final Looper me = myLooper();
if (me == null) {
throw new RuntimeException("No Looper; Looper.prepare() wasn't called on this thread.");
}
for (;;) {
if (!loopOnce(me, ident, thresholdOverride)) {
return;
}
}
}
//保留主要代码
private static boolean loopOnce(final android.os.Looper me,
final long ident, final int thresholdOverride) {
//获取message
Message msg = me.mQueue.next(); // might block
if (msg == null) {
// No message indicates that the message queue is quitting.
return false;
}
//target为目标handler,调用dispatchMessage将消息传入
msg.target.dispatchMessage(msg);
//回收msg
msg.recycleUnchecked();
return true;
}
//释放资源
public void quit() {
mQueue.quit(false);
}
}
MessageQueue
MessageQueue有序消息队列,持有消息。被Looper和Handler持有,但是仅在Looper中初始化。
主要实现:
内部持有Message类型变量messages做消息存储,和boolean类型变量mQuiting,做退出标志。
enqueueMessage():添加消息方法,将Message标记为已用,根据传入时间进行插入排序,存入链表messages中,唤醒循环
next():无限循环,获取并返回链表messages中的下一个消息。若遇到同步屏障,则轮询链表找出最近一个异步消息并返回;否则,按队列顺序找到第一个消息,若执行时间未到,则陷入休眠,时间到时再唤醒(此处调用native方法),若正常获取到消息并且可以立即直接,则直接返回此消息。若消息队列为空,为空则执行闲时任务,在下一次循环时进入休眠等enqueueMessage()唤醒循环,若已退出,则退出循环,释放资源。
public final class MessageQueue {
//标记是否可以退出
private final boolean mQuitAllowed;
//消息链表
Message mMessages;
//退出标记
private boolean mQuitting;
//保留主要代码
boolean enqueueMessage(Message msg, long when) {
//目标handler不能为空
if (msg.target == null) {
throw new IllegalArgumentException("Message must have a target.");
}
//可能多个线程发消息
synchronized (this) {
//已经退出,直接回收msg
if (mQuitting) {
IllegalStateException e = new IllegalStateException(
msg.target + " sending message to a Handler on a dead thread");
Log.w(TAG, e.getMessage(), e);
msg.recycle();
return false;
}
msg.when = when;
Message p = mMessages;
boolean needWake; //是否需要唤醒
if (p == null || when == 0 || when < p.when) {
// 插入到头部并唤醒:队列为空||延时为0的即时消息||新消息延时比队首消息延时更短
msg.next = p;
mMessages = msg;
needWake = mBlocked;//出队方法next是否被阻塞在pollOnce()处(nextPollTimeoutMillis≠0)
} else {
//插入队列中间的唤醒条件:队首为同步屏障消息,且插入的是异步消息
needWake = mBlocked && p.target == null && msg.isAsynchronous();
Message prev;
for (;;) {
//向后递归根据时间寻找插入位置或者插入队尾
prev = p;
p = p.next;
if (p == null || when < p.when) {
break;
}
//如果在新消息前有更早的异步异步消息,则不进行唤醒
if (needWake && p.isAsynchronous()) {
needWake = false;
}
}
msg.next = p; // invariant: p == prev.next
prev.next = msg;
}
// 唤醒线程,nativePollOnce不在阻塞
if (needWake) {
nativeWake(mPtr);
}
}
return true;
}
Message next() {
final long ptr = mPtr;/*MessageQueue 的native层地址*/
if (ptr == 0) {//当消息循环已经退出,则直接返回
return null;
}
int pendingIdleHandlerCount = -1; //待处理闲时handler数量
int nextPollTimeoutMillis = 0;
for (;;) {
nativePollOnce(ptr, nextPollTimeoutMillis); //阻塞 类似Object.wait()
synchronized (this) {
final long now = SystemClock.uptimeMillis();
Message prevMsg = null;
Message msg = mMessages;
//如果队首是同步屏障消息,则循环查找最近的异步消息
if (msg != null && msg.target == null) {
do {
prevMsg = msg;
msg = msg.next;
} while (msg != null && !msg.isAsynchronous());
}
if (msg != null) {
//如果待处理的msg未到处理时间
if (now < msg.when) {
//更新阻塞时间
nextPollTimeoutMillis = (int) Math.min(msg.when - now, Integer.MAX_VALUE);
} else {
// 是否被阻塞,设置为false,供enqueueMessage()使用
mBlocked = false;
//如果是异步消息,则在链表中部删除msg
if (prevMsg != null) {
prevMsg.next = msg.next;
} else {
//不是异步消息,队首后移
mMessages = msg.next;
}
//置空next
msg.next = null;
msg.markInUse();
return msg;
}
} else {
// 队列中没有msg,设为-1,下个for循环时线程阻塞
nextPollTimeoutMillis = -1;
}
/*------------------------------空闲handler处理----------------------------------*/
/* Idlehandles仅在队列为空或队首消息时机未到时才运行*/
//获取闲时任务量
if (pendingIdleHandlerCount < 0
&& (mMessages == null || now < mMessages.when)) {
pendingIdleHandlerCount = mIdleHandlers.size();
}
//如果闲时任务为空则跳入下次循环
if (pendingIdleHandlerCount <= 0) {
// No idle handlers to run. Loop and wait some more.
mBlocked = true;
continue;
}
if (mPendingIdleHandlers == null) {
mPendingIdleHandlers = new IdleHandler[Math.max(pendingIdleHandlerCount, 4)];
}
mPendingIdleHandlers = mIdleHandlers.toArray(mPendingIdleHandlers);
}
//执行闲时任务
for (int i = 0; i < pendingIdleHandlerCount; i++) {
final IdleHandler idler = mPendingIdleHandlers[i];
mPendingIdleHandlers[i] = null; // release the reference to the handler
//执行IdleHandler的queueIdle方法,运行IdelHandler
idler.queueIdle();
}
/*执行完闲时Handler重置闲时计数和下次延迟时间*/
pendingIdleHandlerCount = 0;
// 因为执行闲时Handler过程中,可能有新消息enqueue,需要重新检查。
// 下次延迟时间置0,下次循环时不阻塞。
nextPollTimeoutMillis = 0;
}
}
}
Message
Message消息类,数据结构为单向链表,持有多个参数,由MessageQueue持有,使用享元设计模式。
主要实现:
Int what:消息标志
long when:消息执行时间戳
Handler target:send此消息的handler
Message next:指向下一消息
Message sPool:消息池,持有空Message
int flags: 存储flag信息(存储isUse和isAsynchronous等)
Messenger replyTo:内部持有handler,用作回调
obtain():从消息池中获取空message
recycle():回收消息并存入消息池
public final class Message implements Parcelable {
public int what;
public int arg1;
public int arg2;
public Object obj;
public Messenger replyTo;
public long when;
Bundle data;
Handler target;
int flags;
Runnable callback;
Message next;
private static Message sPool;
public static android.os.Message obtain() {
synchronized (sPoolSync) {
if (sPool != null) {
android.os.Message m = sPool;
sPool = m.next;
m.next = null;
m.flags = 0; // clear in-use flag
sPoolSize--;
return m;
}
}
return new android.os.Message();
}
public static Message obtain(Handler h, int what) {
android.os.Message m = obtain();
m.target = h;
m.what = what;
return m;
}
public void recycle() {
if (isInUse()) {
if (gCheckRecycle) {
throw new IllegalStateException("This message cannot be recycled because it "
+ "is still in use.");
}
return;
}
recycleUnchecked();
}
}
Handler
Handler工具类,发送和处理消息。构造方法需传入looper,获取此looper种MessageQueue并持有。
主要实现:
MessageQueue messageQueue:消息队列,用于存入消息(非new出,是取自Looper中)
enqueueMessage(): 此方法中将this存入message中target,并调用messageQueue的enqueueMessage()存入消息队列。
dispatchMessage():获取到将要处理的消息,传入handleMessage(),此方法有Looper调用
handleMessage():由外部实现,真正对message进行处理。
public class Handler {
final Looper mLooper;
final MessageQueue mQueue;
final Callback mCallback;
final boolean mAsynchronous;
public interface Callback {
boolean handleMessage(@NonNull Message msg);
}
//使用者实现此方法
public void handleMessage(@NonNull Message msg) {
}
public Handler(@NonNull Looper looper, @Nullable Callback callback, boolean async) {
mLooper = looper;
//获取looper中MessageQueue
mQueue = looper.mQueue;
mCallback = callback;
mAsynchronous = async;
}
//looper在loop时调用此方法将消息分发过来
//执行callback和handleMessage
public void dispatchMessage(@NonNull Message msg) {
if (msg.callback != null) {
handleCallback(msg);
} else {
if (mCallback != null) {
if (mCallback.handleMessage(msg)) {
return;
}
}
handleMessage(msg);
}
}
//在消息池中获取一个Massage
public final Message obtainMessage() {
return Message.obtain(this);
}
//向队列中添加消息 调用MessageQueue.enqueueMessage()
private boolean enqueueMessage(@NonNull MessageQueue queue, @NonNull Message msg,
long uptimeMillis) {
msg.target = this;
msg.workSourceUid = ThreadLocalWorkSource.getUid();
if (mAsynchronous) {
msg.setAsynchronous(true);
}
return queue.enqueueMessage(msg, uptimeMillis);
}
}