本文主要介绍了关于线程、处理程序和HandlerThread之间关系的详细解释的相关信息。有需要的朋友可以参考一下。
前言
前几天看到一个面试问题:Thread,Handler和HandlerThread有什么区别?这个话题有意思。对于很多人来说,可能对Thread和Handler比较熟悉,它主要涉及Android的消息机制(Handler、Message、Looper、MessageQueue)。详情见《从Handler.post(Runnable r)再一次梳理Android的消息机制(以及handler的内存泄露)》。
但是这个手柄线程是用来做什么的呢?是处理程序还是线程?我们知道Handler是用来异步更新UI的,更确切地说,是用来在线程之间进行通信的。更新UI时,是子线程和UI主线程之间的通信。现在,如果我们想要在子线程之间进行通信,我们应该做什么?最后当然也是用HandlerThread完成的(不推荐,需要自己操作Looper)。Google官方很好心的帮我们打包了一个类,就是我们刚才说的:Handler Thread。(类似的封装包括针对多线程场景的AsyncTask)
使用方法
我们先来看看HandlerThread的用法:
首先,创建一个新的HandlerThread并执行start()
私有句柄mHandlerThread
.
mHandlerThread=new handler thread( handler thread );
handler thread . start();
创建处理程序并使用mHandlerThread.getLooper()生成Looper:
最终处理程序handler=新处理程序(mHandlerThread.getLooper()){
@覆盖
公共void handleMessage(Message msg) {
System.out.println(已接收消息);
}
};
然后创建一个新的子线程来发送消息:
新线程(新Runnable() {
@覆盖
公共无效运行(){
尝试{
thread . sleep(1000);//模拟耗时的操作
handler . senemptymessage(0);
} catch (InterruptedException e) {
e . printstacktrace();
}
}
}).start();
最后,不要忘记在灾难时释放它,以避免内存泄漏:
@覆盖
受保护的void onDestroy() {
super . on destroy();
mhandlerthread . quit();
}
结果非常简单,即在控制台上打印字符串:message received。
原理
在整个使用过程中我们完全不用关心Handler相关的事情,我们只需要发送消息,处理消息,把Looper相关的事情留给它自己。我们来看看源代码是如何实现的,先看构造方法:
公共类处理程序线程扩展线程{}
HandlerThread其实就是一个线程。和普通螺纹有什么不同?
公共类处理程序线程扩展线程{
int mPriority
int mTid=-1;
Looper mLooper
公共句柄线程(字符串名称){
超级(名);
mPriority=过程。线程优先级默认值;
}
.
}
答案是多了一个Looper,是子线程独有的,用来取消息和处理消息。继续看HandlerThread这个线程的运行方法:
受保护的void onLooperPrepared() {
}
@覆盖
公共无效运行(){
mTid=process . mytid();
looper . prepare();
同步(这){
m looper=looper . my looper();//生成活套
notify all();
}
process . setthreadpriority(m priority);
onLooperPrepared();//空方法,在创建Looper后调用。你可以自己重写逻辑。
looper . loop();//无限循环,不断从MessageQueue中取出消息,交给Handler处理。
mTid=-1;
}
主要做一些Looper操作,如果我们自己用Handler线程来实现,也要做这个操作。让我们来看看getLooper()方法:
公共Looper getLooper() {
如果(!isAlive()) {
返回null
}
//如果线程已经启动,等待直到创建了looper。
同步(这){
while (isAlive() mLooper==null) {
尝试{
wait();
} catch (InterruptedException e) {
}
}
}
返回mLooper
}
方法很简单,就是加一个同步锁。如果已经创建(isAlive()返回true)但mLooper为空,则继续等待,直到mLooper创建成功。最后看戒法。值得一提的有两条:
public boolean quit() {
looper looper=get looper();
如果(looper!=null) {
looper . quit();
返回true
}
返回false
}
public boolean quitSafely() {
looper looper=get looper();
如果(looper!=null) {
looper . quit safely();
返回true
}
返回false
}
QuitSafely指的是消息队列中仍然有消息或者延迟的消息没有被处理的情况。调用此方法后,它将被停止。
总结
HandlerThread的使用相对简单,但是我们需要明白一点:如果一个线程要处理消息,它必须有自己的Looper,无论在哪里创建Handler,它都可以处理消息。
如果不使用HandlerThread,需要手动调用Looper.prepare()和Looper.loop()方法。
以上是Thread、Handler和HandlerThread的数据整理,后续我们会继续补充相关数据。感谢您对本站的支持!