本文要大力感谢Android性能优化典范之多线程篇,博主大力推荐公众号
作为腾讯旗下的一款公众号,不定期推送一些高质量的技术文章,博主受益匪浅,在此和大家分享。
说起Android的并发,常见的方式大概有这么几种:
- AsyncTask: 为 UI 线程与工作线程之间进行快速的切换提供一种简单便捷的机制。适用于当下立即需要启动,但是异步执行的生命周期短暂的使用场景。
- HandlerThread: 为某些回调方法或者等待某些任务的执行设置一个专属的线程,并提供线程任务的调度机制。
- IntentService: 适合于执行由 UI 触发的后台 Service 任务,并可以把后台任务执行的情况通过一定的机制反馈给 UI。
- ThreadPool: 把任务分解成不同的单元,分发到各个不同的线程上,进行同时并发处理。
前三种方式都离不开Handler+MessageQueue+Looper,而且IntentService是HandlerThread+Service的结合。关于Handler、MessageQueue、Looper已经在Android进阶系列9-Android异步消息处理Handler机制解析中讲述,AsyncTask在Android进阶系列10-AsyncTask分析中分析了。HandlerThread和IntentService我们简要提下,比较简单,就不详述。
HandlerThread
public class HandlerThread extends Thread {
int mPriority;
int mTid = -1;
Looper mLooper;
/*构造函数*/
public HandlerThread(String name) {
super(name);
mPriority = Process.THREAD_PRIORITY_DEFAULT;
}
/*构造函数*/
public HandlerThread(String name, int priority) {
super(name);
mPriority = priority;
}
/*在Looper.loop()之前调用的方法*/
protected void onLooperPrepared() {
}
@Override
public void run() {
mTid = Process.myTid();
Looper.prepare();
synchronized (this) {
mLooper = Looper.myLooper();
notifyAll();//对象初始化后唤醒获取对象的方法getLooper()
}
Process.setThreadPriority(mPriority);
onLooperPrepared();
Looper.loop();
mTid = -1;
}
/*返回线程对应的Looper对象,阻塞式获取*/
public Looper getLooper() {
if (!isAlive()) {
return null;
}
/*保证获取到非空的mLooper*/
synchronized (this) {
while (isAlive() && mLooper == null) {
try {
wait();
} catch (InterruptedException e) {
}
}
}
return mLooper;
}
/*立即退出Looper*/
public boolean quit() {
Looper looper = getLooper();
if (looper != null) {
looper.quit();
return true;
}
return false;
}
/*将正在处理的处理完后,安全退出Looper(不接受新的消息)*/
public boolean quitSafely() {
Looper looper = getLooper();
if (looper != null) {
looper.quitSafely();
return true;
}
return false;
}
/*返回线程id*/
public int getThreadId() {
return mTid;
}
}
HandlerThread,初始化了Looper对象,提供了安全获取对象的getLooper()方法,以及退出Looper的两种方式。
IntentService
public abstract class IntentService extends Service {
private volatile Looper mServiceLooper;
private volatile ServiceHandler mServiceHandler;
private String mName;
private boolean mRedelivery;
/*自定义Handler*/
private final class ServiceHandler extends Handler {
public ServiceHandler(Looper looper) {
super(looper);
}
@Override
public void handleMessage(Message msg) {
/*调用方法处理子线程消息*/
onHandleIntent((Intent)msg.obj);
stopSelf(msg.arg1);
}
}
/*构造函数*/
public IntentService(String name) {
super();
mName = name;
}
//......
@Override
public void onCreate() {
super.onCreate();
/*创建子线程,建立子线程对应的Handler*/
HandlerThread thread = new HandlerThread("IntentService[" + mName + "]");
thread.start();
mServiceLooper = thread.getLooper();
mServiceHandler = new ServiceHandler(mServiceLooper);
}
@Override
public void onStart(Intent intent, int startId) {
/*创建消息并发送给子线程*/
Message msg = mServiceHandler.obtainMessage();
msg.arg1 = startId;
msg.obj = intent;
mServiceHandler.sendMessage(msg);
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
onStart(intent, startId);
return mRedelivery ? START_REDELIVER_INTENT : START_NOT_STICKY;
}
@Override
public void onDestroy() {
/*停止Looper*/
mServiceLooper.quit();
}
//......
/*子线程处理msg的具体实现,子类完成*/
@WorkerThread
protected abstract void onHandleIntent(Intent intent);
}
借助HandlerThread创建子线程,将onHandleIntent()方法内的代码在子线程执行。
不管是哪种方式实现的多线程,无非两个需求:子线程执行,数据切换到主线程。如何开启子线程离不开Thread(不止这一种方式);如何线程间切换数据,离不开Handler(也有其他方法),由此衍生出AsyncTask,HandlerThread和IntentService。外加一个ThreadPool。
关于这四种多线程并发的性能问题,请看Android性能优化典范之多线程篇,等他们授权了,我再把文章贴过来。
总结
很惭愧,做了一点微小的贡献!