参考
Handler和他的小伙伴们(中)
android点滴之HandlerThread的用法
Android HandlerThread 源码分析
Android HandlerThread 完全解析
我们知道Thread线程是一次性消费品,当Thread线程执行完一个耗时的任务之后,线程就会被自动销毁了。如果此时我又有一个耗时任务需要执行,我们不得不重新创建线程去执行该耗时任务。然而,这样就存在一个性能问题:多次创建和销毁线程是很耗系统资源的。为了解决这个问题,我们可以自己构建一个循环线程Looper Thread,当有耗时任务投放到该循环线程中时,线程执行耗时任务,执行完之后循环线程处于等待状态,直到下一个新的耗时任务被投放进来。这样一来就避免了多次创建Thread线程导致的性能问题了。也许你可以自己去构建一个循环线程,但我可以告诉你一个好消息,Android SDK中其实已经有一个循环线程的框架了。此时你只需要掌握其怎么使用的就ok啦!当然就是我们今天的主角HandlerThread啦!接下来请HandlerThread上场,鼓掌~~HandlerThread的父类是Thread,因此HandlerThread其实是一个线程,只不过其内部帮你实现了一个Looper的循环而已。
- Android系统提供的Handler类内部的Looper默认绑定的是UI线程的消息队列,对于非UI线程又想使用消息机制,那么HandlerThread内部的Looper是最合适的,它不会干扰或阻塞UI线程。HandlerThread适合在只需要一个工作线程(非UI线程)+任务的等待队列的形式,优点是不会有堵塞,减少了对性能的消耗,缺点是不能同时进行多任务的处理,需要等待进行处理。处理效率较低。
- 与线程池注重并发不同,HandlerThread是一个串行队列,HandlerThread背后只有一个线程。串行相对于并行来说更安全,各任务之间不会存在多线程安全问题。
一、原理
HandlerThread继承了Thread,它是一种可以使用Handler的Thread。它的实现很简单,就是在run方法中通过Loop.prepare()来创建消息队列,并通过Loop.loop()来开启消息循环,这样在实际的使用中就允许在HandlerThread中创建Handler了。
package android.os;
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;
}
}
从HandlerThread的实现来看,普通Thread主要用于在run方法中执行一个耗时任务,而HandlerThread在内部创建了消息队列,外界需要通过Handler的消息方式来通知HandlerThread执行一个具体的任务。
二、使用步骤
1.创建实例对象
HandlerThread handlerThread = new HandlerThread("handlerThread");
以上参数可以任意字符串,参数的作用主要是标记当前线程的名字。
2.启动HandlerThread线程
handlerThread.start();
到此,我们就构建完一个循环线程了。那么你可能会怀疑,那我怎么将一个耗时的异步任务投放到HandlerThread线程中去执行呢?当然是有办法的,接下来看第三步。
3.构建循环消息处理机制
Handler subHandler = new Handler(handlerThread.getLooper(), new Handler.Callback() {
@Override
public boolean handleMessage(Message msg) {
//实现自己的消息处理
return true;
}
});
第三步创建一个Handler对象,将上面HandlerThread中的looper对象作为Handler的参数,然后重写Handler的Callback接口类中的handlerMessage方法来处理耗时任务。
package com.example.handlerthread;
import android.app.Activity;
import android.os.Bundle;
import android.os.Handler;
import android.os.HandlerThread;
import android.os.Message;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.TextView;
public class MainActivity extends Activity {
private Handler mSubHandler;
private TextView textView;
private Button button;
private Handler.Callback mSubCallback = new Handler.Callback() {
//该接口的实现就是处理异步耗时任务的,因此该方法执行在子线程中
@Override
public boolean handleMessage(Message msg) {
switch (msg.what) {
case 0:
Message msg1 = new Message();
msg1.what = 0;
msg1.obj = java.lang.System.currentTimeMillis();
mUIHandler.sendMessage(msg1);
break;
default:
break;
}
return false;
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
textView = (TextView) findViewById(R.id.textView);
button = (Button) findViewById(R.id.button);
HandlerThread workHandle = new HandlerThread("workHandleThread");
workHandle.start();
mSubHandler = new Handler(workHandle.getLooper(), mSubCallback);
button.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
//投放异步耗时任务到HandlerThread中
mSubHandler.sendEmptyMessage(0);
}
});
}
}
三、例子
package com.zhy.blogcodes.intentservice;
import android.os.Bundle;
import android.os.Handler;
import android.os.HandlerThread;
import android.os.Message;
import android.support.v7.app.AppCompatActivity;
import android.text.Html;
import android.widget.TextView;
import com.zhy.blogcodes.R;
public class HandlerThreadActivity extends AppCompatActivity
{
private TextView mTvServiceInfo;
private HandlerThread mCheckMsgThread;
private Handler mCheckMsgHandler;
private boolean isUpdateInfo;
private static final int MSG_UPDATE_INFO = 0x110;
//与UI线程管理的handler
private Handler mHandler = new Handler();
@Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_thread_handler);
//创建后台线程
initBackThread();
mTvServiceInfo = (TextView) findViewById(R.id.id_textview);
}
@Override
protected void onResume()
{
super.onResume();
//开始查询
isUpdateInfo = true;
mCheckMsgHandler.sendEmptyMessage(MSG_UPDATE_INFO);
}
@Override
protected void onPause()
{
super.onPause();
//停止查询
isUpdateInfo = false;
mCheckMsgHandler.removeMessages(MSG_UPDATE_INFO);
}
private void initBackThread()
{
mCheckMsgThread = new HandlerThread("check-message-coming");
mCheckMsgThread.start();
mCheckMsgHandler = new Handler(mCheckMsgThread.getLooper())
{
@Override
public void handleMessage(Message msg)
{
checkForUpdate();
if (isUpdateInfo)
{
mCheckMsgHandler.sendEmptyMessageDelayed(MSG_UPDATE_INFO, 1000);
}
}
};
}
/**
* 模拟从服务器解析数据
*/
private void checkForUpdate()
{
try
{
//模拟耗时
Thread.sleep(1000);
mHandler.post(new Runnable()
{
@Override
public void run()
{
String result = "实时更新中,当前大盘指数:%d";
result = String.format(result, (int) (Math.random() * 3000 + 1000));
mTvServiceInfo.setText(Html.fromHtml(result));
}
});
} catch (InterruptedException e)
{
e.printStackTrace();
}
}
@Override
protected void onDestroy()
{
super.onDestroy();
//释放资源
mCheckMsgThread.quit();
}
}
a