HandlerThread分析

Posted by alonealice on 2016-09-07

HandlerThread是Thread的子类,它可以创建一个looper。而该looper对象可以用于创建Handler类来进行来进行调度。之前在用它时有两个疑问:一是Looper是在哪里创建的,二是怎样保证Looper是在创建之后才被使用。接下来通过HandlerThread的源码来看看它是如何实现的。
HandlerThread的源码十分简短,总共才100多行。
首先看看其构造方法:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
public HandlerThread(String name) {
super(name);
mPriority = Process.THREAD_PRIORITY_DEFAULT;
}

/**
* Constructs a HandlerThread.
* @param name
* @param priority The priority to run the thread at. The value supplied must be from
* {@link android.os.Process} and not from java.lang.Thread.
*/
public HandlerThread(String name, int priority) {
super(name);
mPriority = priority;
}

构造方法其实啥也没干,就是简单的记录线程的name和优先级。
再看看run方法:

1
2
3
4
5
6
7
8
9
10
11
12
13
@Override
public void run() {
mTid = Process.myTid();
Looper.prepare();
synchronized (this) {
mLooper = Looper.myLooper();
notifyAll();
}
Process.setThreadPriority(mPriority);
onLooperPrepared();
Looper.loop();
mTid = -1;
}

这里我们看到了,Looper是在run方法中被创建的。在创建完成之后,用了同步锁将looper实例初始化锁了起来,这里用了同步,是为了避免在getLooper时程序无法被唤醒。最后开始循环looper。
然后看看getLooper方法:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
public Looper getLooper() {
if (!isAlive()) {
return null;
}

// If the thread has been started, wait until the looper has been created.
synchronized (this) {
while (isAlive() && mLooper == null) {
try {
wait();
} catch (InterruptedException e) {
}
}
}
return mLooper;
}

首先,looper的获取必须要在线程在alive状态,因此说明在使用时必须先调用onStart方法,在获取这个looper,其次,当looper为null时,程序将等待阻塞,直到在run方法中唤醒程序,返回looper。
当不在需要该looper时,可以将looper退出:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
public boolean quit() {
Looper looper = getLooper();
if (looper != null) {
looper.quit();
return true;
}
return false;
}

public boolean quitSafely() {
Looper looper = getLooper();
if (looper != null) {
looper.quitSafely();
return true;
}
return false;
}

最后回答之前的两个问题,首先Looper是在run方法中创建的,同时用到了synchronized来避免出现同步问题;在looper获取过程中,如果looper还没有创建,那会阻塞等待run中创建完成之后重新唤醒。