未完待续!!!!!!
Handler
看电视剧的时候突然有感而发。可以把Handler机制,和机场传送带结合起来(我这个传送带比较高级,有行李的时候就转动,没有行李的时候就待机)。
- Looper.loop() :比作传送带的机器(动力来源)。
- MessageQueue:比作传送带。
- Handler:比作 分拣员,负责向传送带放行李取行李。
- Message:比作行李框(有的机场防止行李变脏)。
- Message对象的内容:比作 行李。
为了方便记忆和学习,假设:主线程MessageQueue没有Message导致主线程block,这时一个Activity执行mHandler.sendMessage();
将这个过程分为 5步:
- 1:通电(Looper.loop()),block(nativePollOnce()).
- 2:放行李(mHandler.sendMessage() -> nativeWake()).
- 3:传送带转起来.
- 4:取行李 Handler.dispatch().
- 5:循环使用 Message.recycleUnchecked().
1:通电
frameworks\base\core\java\android\app\ActivityThread.java
// 1:main方法入口
public static void main(String[] args) {
...
// 2:
Looper.prepareMainLooper();
ActivityThread thread = new ActivityThread();
thread.attach(false);
...
// 8:
Looper.loop();
throw new RuntimeException("Main thread loop unexpectedly exited");
}
frameworks\base\core\java\android\os\Looper.java
static final ThreadLocal<Looper> sThreadLocal = new ThreadLocal<Looper>();//进程内唯一
// 构造方法private,只能通过 prepare创建Looper对象
private Looper(boolean quitAllowed) {
mQueue = new MessageQueue(quitAllowed);
mThread = Thread.currentThread();
}
public static void prepare() {
prepare(true);
}
// 4:
//保证一个线程对应一个Looper,一个Looper对应一个MessageQueue。
private static void prepare(boolean quitAllowed) {
if (sThreadLocal.get() != null) {
throw new RuntimeException("Only one Looper may be created per thread");
}
// 5:
sThreadLocal.set(new Looper(quitAllowed));
}
// 3:
public static void prepareMainLooper() {
prepare(false);
synchronized (Looper.class) {
if (sMainLooper != null) {
throw new IllegalStateException("The main Looper has already been prepared.");
}
sMainLooper = myLooper();
}
}
// 9:
public static void loop() {
final Looper me = myLooper();// sThreadLocal.get()
if (me == null) {
throw new RuntimeException("No Looper; Looper.prepare() wasn't called on this thread.");
}
final MessageQueue queue = me.mQueue;
for (;;) {
// 10:
Message msg = queue.next(); // might block
...
msg.target.dispatchMessage(msg);//这是handler内存泄漏的原因,target是Handler对象
}
}
libcore\ojluni\src\main\java\java\lang\ThreadLocal.java
// 6:
public void set(T value) {
Thread t = Thread.currentThread();
ThreadLocalMap map = getMap(t);
if (map != null)
map.set(this, value);
else
createMap(t, value);
}
static class ThreadLocalMap {
// 7:
private void set(ThreadLocal<?> key, Object value) {
Entry[] tab = table;
int len = tab.length;
int i = key.threadLocalHashCode & (len-1);//这里使用当前threadlocal哈希做下标。
for (Entry e = tab[i];
e != null;
e = tab[i = nextIndex(i, len)]) {
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();
}
}
frameworks\base\core\java\android\os\MessageQueue.java
Message next() {
...
for (;;) {
... // 12: 没消息时阻塞
nativePollOnce(ptr, nextPollTimeoutMillis);//阻塞操作
...
}
boolean enqueueMessage(Message msg, long when) {
...
nativeWake(mPtr);
return true;
}
2:放行李
Handler.java
// 1:sendMessage 最终调用
private boolean enqueueMessage(MessageQueue queue, Message msg, long uptimeMillis) {
msg.target = this;//Message引用Handler.
if (mAsynchronous) {
msg.setAsynchronous(true);
}
// 2:
return queue.enqueueMessage(msg, uptimeMillis);
}
MessageQueue.java
Message next() {
...
for (;;) {
...
nativePollOnce(ptr, nextPollTimeoutMillis);//阻塞操作
...
}
// 3:
boolean enqueueMessage(Message msg, long when) {
...
// 4:
nativeWake(mPtr);
return true;
}
3:传送带动起来
4:取行李
Looper.java
public static void loop() {
final Looper me = myLooper();// sThreadLocal.get()
if (me == null) {
throw new RuntimeException("No Looper; Looper.prepare() wasn't called on this thread.");
}
final MessageQueue queue = me.mQueue;
for (;;) {
Message msg = queue.next(); // might block
...
// 1:
msg.target.dispatchMessage(msg);//这是handler内存泄漏的原因,target是Handler对象
...
msg.recycleUnchecked();
}
}
Handler.java
// 2: 链式调用
public void dispatchMessage(Message msg) {
if (msg.callback != null) {
handleCallback(msg);
} else {
if (mCallback != null) {
if (mCallback.handleMessage(msg)) {
return;
}
}
handleMessage(msg);
}
}
5:循环使用 Message
Looper.java
public static void loop() {
final Looper me = myLooper();// sThreadLocal.get()
if (me == null) {
throw new RuntimeException("No Looper; Looper.prepare() wasn't called on this thread.");
}
final MessageQueue queue = me.mQueue;
for (;;) {
Message msg = queue.next(); // might block
...
msg.target.dispatchMessage(msg);//这是handler内存泄漏的原因,target是Handler对象
...
// 1:
msg.recycleUnchecked();
}
}
Message.java
// 2:
void recycleUnchecked() {
// Mark the message as in use while it remains in the recycled object pool.
// Clear out all other details.
flags = FLAG_IN_USE;
what = 0;
arg1 = 0;
arg2 = 0;
obj = null;
replyTo = null;
sendingUid = -1;
when = 0;
target = null;
callback = null;
data = null;
// 享元设计模式 Message池容量 50 ,超过50直接丢弃,等待GC
synchronized (sPoolSync) {
if (sPoolSize < MAX_POOL_SIZE) { //MAX_POOL_SIZE = 50
next = sPool;
sPool = this;
sPoolSize++;
}
}
}
如何保证一个线程只有一个looper
- 1:Looper构造方法私有化
- 2:只提供prepare()创建Looper对象
- 3:使用 static final 保证 ,当前进程只有一个 sThreadLocal。
一个Thread对应一个ThreadLocal.ThreadLocalMap存储 ThreadLocal数据. 一个Thread对应多个ThreadLocal。一个ThreadLocal只能存储一个数据。
- 4:sThreadLocal.set(new Looper(quitAllowed)).使用
Looper.java
//3:使用 static final 保证 ,当前进程只有一个 sThreadLocal。
static final ThreadLocal<Looper> sThreadLocal = new ThreadLocal<Looper>();
//1:构造方法私有化
private Looper(boolean quitAllowed) {
mQueue = new MessageQueue(quitAllowed);
mThread = Thread.currentThread();
}
//2:只提供prepare()创建Looper对象
public static void prepare() {
prepare(true);
}
private static void prepare(boolean quitAllowed) {
if (sThreadLocal.get() != null) {
throw new RuntimeException("Only one Looper may be created per thread");
}
sThreadLocal.set(new Looper(quitAllowed));
}
public static void prepareMainLooper() {
prepare(false);
synchronized (Looper.class) {
if (sMainLooper != null) {
throw new IllegalStateException("The main Looper has already been prepared.");
}
sMainLooper = myLooper();
}
}
ThreadLocal.java
- Java标准库提供了一个特殊的ThreadLocal,它可以在一个线程中传递同一个对象。
public void set(T value) {
Thread t = Thread.currentThread();
ThreadLocalMap map = getMap(t);//最终返回 Thread.java 的 ThreadLocal.ThreadLocalMap threadLocals;
if (map != null)
map.set(this, value);
else
createMap(t, value);
}
static class ThreadLocalMap {
static class Entry extends WeakReference<ThreadLocal<?>> {
Object value;
Entry(ThreadLocal<?> k, Object v) {
super(k);
value = v;
}
}
private Entry[] table;
private void set(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)]) {
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();
}
}
线程切换
线程切换 本质就是 线程切换执行 共享的资源。
- 1:在主线程 Handler mHandler = new Handler(); 得到mHandler.mQueue MessageQueue
- 2:在子线程 mHandler.sendMessage();
Handler.java
// 2: 子线程
public boolean sendMessageAtTime(Message msg, long uptimeMillis) {
MessageQueue queue = mQueue; // 共享的 MessageQueue
if (queue == null) {
RuntimeException e = new RuntimeException(
this + " sendMessageAtTime() called with no mQueue");
Log.w("Looper", e.getMessage(), e);
return false;
}
return enqueueMessage(queue, msg, uptimeMillis);
}
// 1:主线程 Handler 实例化
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());
}
}
mLooper = Looper.myLooper();//主线程已经 main() ->prepare()
if (mLooper == null) {
throw new RuntimeException(
"Can't create handler inside thread that has not called Looper.prepare()");
}
mQueue = mLooper.mQueue; // 共享的 MessageQueue
mCallback = callback;
mAsynchronous = async;
}