HandlerThread是什么?
HandlerThread
继承了Thread
,它是一种可以使用Handler
的Thread
。它和普通的Thread
有显著的不同之处:普通Thread
主要用于在run方法中执行一个耗时任务,而HandlerThread在内部创建了消息队列,外界需要通过Handler
的消息方式来通知HandlerThread
执行一个具体的任务。
在子线程创建Handler
上篇文章分析了Handler
+Thread
异步操作的原理,但是我们创建的Handler
都是在主线程,那么可不可以在子线程也来创建一个Handler
了?
new Thread(){
@Override
public void run() {
Looper.prepare();
Handler handler = new Handler(Looper.myLooper());
Looper.loop();
}
}.start();
可是可以,但这样是不是觉得有点麻烦了?
不过Android已经帮我们封装好了,那就是我们今天的主角:HandlerThread
HanlderThread基本用法
public class MainActivity extends AppCompatActivity {
private HandlerThread mThread;
private Handler mThreadHandler;
private MyRunnable mRunnable;
private MyRunnable mRunnable2;
private TextView mText;
private TextView mTextTwo;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mText = (TextView) findViewById(R.id.tv_text);
mTextTwo = (TextView) findViewById(R.id.tv_text2);
mThread = new HandlerThread("MainActivity");
//HandlerThread本质还是线程,所以必须start起来
mThread.start();
//将线程与HandlerThread绑定在一起
mThreadHandler = new Handler(mThread.getLooper());
}
public void begin(View view) {
mRunnable = new MyRunnable(this, 1);
mRunnable2 = new MyRunnable(this, 2);
mThreadHandler.post(mRunnable);
mThreadHandler.post(mRunnable2);
}
private static class MyRunnable implements Runnable {
private final WeakReference<MainActivity> mActivity;
private int mOrder;
public MyRunnable(MainActivity mainActivity, int order) {
this.mActivity = new WeakReference<>(mainActivity);
this.mOrder = order;
}
@Override
public void run() {
final MainActivity activity = mActivity.get();
//模拟耗时操作
SystemClock.sleep(3000);
activity.runOnUiThread(new Runnable() {
@Override
public void run() {
if (mOrder == 1) {
activity.mText.setText("我是任务一");
} else {
activity.mTextTwo.setText("我是任务二");
}
}
});
}
}
@Override
protected void onDestroy() {
super.onDestroy();
mThreadHandler.removeCallbacks(mRunnable);
mThreadHandler.removeCallbacks(mRunnable2);
//终止线程
mThread.quit();//还可以使用mThread.quitSafely();
}
}
Demo非常简单,就是通过handler提交两个耗时任务给HandlerThread,从效果图来看,很显然耗时任务是按顺序执行的。所以,HandlerThread适用于单线程+异步队列模型场景
源码分析
我们在demo中创建HandlerThread
的实例对象并启动了该线程,看看源码如何实现的:
public class HandlerThread extends Thread {
int mPriority;
int mTid = -1;
Looper mLooper;
public HandlerThread(String name) {
super(name);
mPriority = Process.THREAD_PRIORITY_DEFAULT;
}
protected void onLooperPrepared() {
}
@Override
public void run() {
mTid = Process.myTid();
Looper.prepare();
synchronized (this) {
mLooper = Looper.myLooper();
notifyAll();
}
Process.setThreadPriority(mPriority);
onLooperPrepared();
Looper.loop();
mTid = -1;
}
是不是和我们在上文提到的自己在子线程创建Handler
的代码相似,是的。不过它给HandlerThread
设置了优先级(Priority)
线程优先级
新创建的线程的优先级默认和创建它的母线程保持一致,为了不让新创建的工作线程和UI线程抢占CPU资源,我们可以见降低工作线程的优先级。Android系统提供了一些优先级值:
HREAD_PRIORITY_DEFAULT,值为0
THREAD_PRIORITY_LOWEST,值为19
THREAD_PRIORITY_BACKGROUND 值为10
THREAD_PRIORITY_MORE_FAVORABLE 值为-1
THREAD_PRIORITY_LESS_FAVORABLE 值为1
线程的优先级的取值范围为-20到19。值越小,优先级越高,而优先级高的获得的CPU资源更多,反之则越少。而源码中给HandlerThread设置的优先级值为:Process.THREAD_PRIORITY_DEFAULT
。即然我们的HandlerThread
是用来处理后台任务的,我们可以将其优先级值设为:THREAD_PRIORITY_BACKGROUND
,可以用通过它的构造方法来设置
mThread = new HandlerThread("MainActivity",Process.THREAD_PRIORITY_BACKGROUND);
注意
与HandlerThread
绑定的Handler
属于子线程,是不能直接更新UI的,我们可以通过runOnUiThread(Runnable r)
来进行线程的切换。