谈到Android的多线程,绕不开Looper,首先我们看看一般来说是Android是如何进行线程间通信的:
* <pre>
* class LooperThread extends Thread {
* public Handler mHandler;
*
* public void run() {
* Looper.prepare();
*
* mHandler = new Handler() {
* public void handleMessage(Message msg) {
* // process incoming messages here
* }
* };
*
* Looper.loop();
* }
* }</pre>
首先要有Looper.prepare();
然后new一个Handler
最后Looper.loop();
我们今天就从源码层面深度分析实现原理:
首先看Looper中定义的变量:
private static final String TAG = "Looper";
//利用虚拟机来进行单例的实现,sThreadLocal 应该是存储Looper对象的一个集合
static final ThreadLocal<Looper> sThreadLocal = new ThreadLocal<Looper>();
//主线程的Looper对象
private static Looper sMainLooper;
//存储线程发来的Message对象
final MessageQueue mQueue;
//当前线程
final Thread mThread;
//打印日志有关
private Printer mLogging;
现在我们看Looper.prepare();中做了什么:
public static void prepare() {
prepare(true);
}
private static void prepare(boolean quitAllowed) {
//保证一个线程中只有一个Looper对象
//一个线程对应一个Looper
if (sThreadLocal.get() != null) {
throw new RuntimeException("Only one Looper may be created per thread");
}
//给sThreadLocal中添加一个Looper对象
sThreadLocal.set(new Looper(quitAllowed));
}
然后我们看看mHandler = new Handler()是怎样和Looper关联的:
public Handler() {
this(null, false);
}
public Handler(Callback callback, boolean async) {
if (FIND_POTENTIAL_LEAKS) {
final Class<? extends Handler> klass = getClass();
if ((klass.isAnonymousClass() || klass.isMemberClass() || klass.isLocalClass()) &&
(klass.getModifiers() & Modifier.STATIC) == 0) {
Log.w(TAG, "The following Handler class should be static or leaks might occur: " +
klass.getCanonicalName());
}
}
//通过Looper.myLooper()得到当前线程的Looper对象
mLooper = Looper.myLooper();
if (mLooper == null) {
throw new RuntimeException(
"Can't create handler inside thread that has not called Looper.prepare()");
}
//得到当前线程Looper里面的MessageQueue对象
mQueue = mLooper.mQueue;
mCallback = callback;
mAsynchronous = async;
}
我们再看看Looper.loop();做了什么:
public static void loop() {
//得到当前线程的Looper对象
final Looper me = myLooper();
if (me == null) {
throw new RuntimeException("No Looper; Looper.prepare() wasn't called on this thread.");
}
//得到MessageQueue集合
final MessageQueue queue = me.mQueue;
// Make sure the identity of this thread is that of the local process,
// and keep track of what that identity token actually is.
Binder.clearCallingIdentity();
final long ident = Binder.clearCallingIdentity();
//进入循环
for (;;) {
//读取MessageQueue集合中的Message
Message msg = queue.next(); // might block
if (msg == null) {
// No message indicates that the message queue is quitting.
return;
}
// This must be in a local variable, in case a UI event sets the logger
Printer logging = me.mLogging;
if (logging != null) {
logging.println(">>>>> Dispatching to " + msg.target + " " +
msg.callback + ": " + msg.what);
}
//处理Message
msg.target.dispatchMessage(msg);
if (logging != null) {
logging.println("<<<<< Finished to " + msg.target + " " + msg.callback);
}
// Make sure that during the course of dispatching the
// identity of the thread wasn't corrupted.
final long newIdent = Binder.clearCallingIdentity();
if (ident != newIdent) {
Log.wtf(TAG, "Thread identity changed from 0x"
+ Long.toHexString(ident) + " to 0x"
+ Long.toHexString(newIdent) + " while dispatching to "
+ msg.target.getClass().getName() + " "
+ msg.callback + " what=" + msg.what);
}
//回收Message
msg.recycle();
}
}
以上就是整个Thread和Looper的关系;但是里面有几个重要的方法:
mLooper = Looper.myLooper();
这个方法是得到当前线程中的Looper对象:
我们看看源码:
public static Looper myLooper() {
//从sThreadLocal中获取
return sThreadLocal.get();
}
结合Looper.prepare中的sThreadLocal.set(new Looper(quitAllowed));
可以看出,不管是获取还是设置Looper对象,都是在sThreadLocal中;
下面重点分析sThreadLocal的实现:
public class ThreadLocal<T> {
public ThreadLocal() {}
从定义可以看出,里面有泛型实现的元素我;们先看看set:
public void set(T value) {
//和当前线程建立联系
Thread currentThread = Thread.currentThread();
//后面看
Values values = values(currentThread);
if (values == null) {
values = initializeValues(currentThread);
}
//将value添加到values
values.put(this, value);
}
也就是说,将Looper对象和线程关联以后,存入到Values这个对象中:后面我接着看Values:
先看看定义和变量:
static class Values {
private static final int INITIAL_SIZE = 16;
private static final Object TOMBSTONE = new Object();
//table是一个Object数组
private Object[] table;
private int mask;
private int size;
private int tombstones;
private int maximumLoad;
private int clean;
我们在看看:values.put(this, value);
void put(ThreadLocal<?> key, Object value) {
cleanUp();
// Keep track of first tombstone. That's where we want to go back
// and add an entry if necessary.
int firstTombstone = -1;
//进入到一个循环中
for (int index = key.hash & mask;; index = next(index)) {
Object k = table[index];
//如果之前存在,那么替换
if (k == key.reference) {
// Replace existing entry.
table[index + 1] = value;
return;
}
//否则,新建一个,然后将value存入到ThreadLocal中
//在Looper中,value其实就是Looper
if (k == null) {
if (firstTombstone == -1) {
// Fill in null slot.
table[index] = key.reference;
table[index + 1] = value;
size++;
return;
}
// Go back and replace first tombstone.
table[firstTombstone] = key.reference;
table[firstTombstone + 1] = value;
tombstones--;
size++;
return;
}
// Remember first tombstone.
if (firstTombstone == -1 && k == TOMBSTONE) {
firstTombstone = index;
}
}
}
其实put就是将Looper对象存储到ThreadLocal对象中的一个Object数组中;加上相应的标记;
我们再看看get
@SuppressWarnings("unchecked")
public T get() {
// Optimized for the fast path.
Thread currentThread = Thread.currentThread();
Values values = values(currentThread);
if (values != null) {
//从Values 中的Object数组中根据标记获取对象
Object[] table = values.table;
int index = hash & values.mask;
if (this.reference == table[index]) {
return (T) table[index + 1];
}
} else {
values = initializeValues(currentThread);
}
//强转
return (T) values.getAfterMiss(this);
}
这下清楚了吧;Looper最后的归宿是在Values中的一个名字叫做table的Object数组中存储;存储的时候添加相关的标记;取的时候根据标记来取;一个Thread中只有一个Looper,一个Looper中有一个MessageQueue,一个MessageQueue中有多个Message;Handler根据Looper来构造,因此一个Thread可以对应多个Handler;以上就是Thread,Looper,MeaageQueue,Handler的关系和之间是如何建立起联系的。