Android中的多线程

Android多线程机制 【Android中的多线程】由于讨论的主要是Android中特有的线程机制和类,因此在此不会再详谈Java中的线程类Thread和Runnable。
Android中可以扮演线程的角色有很多,AsyncTask、IntentService和HandlerThread,AsyncTask的底层实际上就是一个线程池,IntentService的底层实际上就是HandlerThread和Handler,而HandlerThread底层实际上就是Android的消息机制和Thread的组合。
Android中的线程形态 AsyncTask
AsyncTask是一个抽象的泛型类:

public abstract class AsyncTask

AsyncTask的具体使用在这里就不再讨论,我们主要了解其工作原理。
AsyncTask的工作原理 在使用AsyncTask时我们最终都要调用它的execute(Params… params)方法,因此我们从execute方法开始。
public final AsyncTask execute(Params... params) { return executeOnExecutor(sDefaultExecutor, params); }

可以看到execute方法内部调用了executeOnExecutor方法,sDefaultExecutor是一个串行的线程池,一个进程中所有的AsyncTask都在这个线程池中排队执行,这个过程之后再分析,我们先来看看executeOnExecutor方法到底做了些什么事:
public final AsyncTask executeOnExecutor(Executor exec, Params... params) { if (mStatus != Status.PENDING) { switch (mStatus) { case RUNNING: throw new IllegalStateException("Cannot execute task:" + " the task is already running."); case FINISHED: throw new IllegalStateException("Cannot execute task:" + " the task has already been executed " + "(a task can be executed only once)"); } }mStatus = Status.RUNNING; onPreExecute(); mWorker.mParams = params; exec.execute(mFuture); return this; }

在executeOnExecutor()方法中,首先执行了我们在创建AsyncTask对象时重写的onPreExecute()方法,这个方法大家都很熟悉,就是在执行任务前的准备工作,是一个在主线程中执行的方法。接着将参数构造AsyncTask时传入的参数Params包装成FutureTask对象,在Java中FutureTask就是Runnable的升级版,在这里我们把他当做Runnable就行,最后我们将这个FutureTask交给了线程池去执行。于是我们接着来到这个串行线程池类——SerialExecutor的内部:
private static class SerialExecutor implements Executor { final ArrayDeque mTasks = new ArrayDeque(); Runnable mActive; public synchronized void execute(final Runnable r) { mTasks.offer(new Runnable() { public void run() { try { r.run(); } finally { scheduleNext(); } } }); if (mActive == null) { scheduleNext(); } }protected synchronized void scheduleNext() { if ((mActive = mTasks.poll()) != null) { THREAD_POOL_EXECUTOR.execute(mActive); } } }

在SerialExecutor内部的execute方法中,首先将FutureTask加入到了任务队列mTasks中,如果这时候没有活跃的AsyncTask任务的话,就调用scheduleNext()方法执行下一个AsyncTask任务,并且我们发现execute并不是执行线程任务的方法,真正执行执行任务的方法是scheduleNext(),这个方法将AsyncTask任务又转交给了另一个线程池THREAD_POOL_EXECUTOR去执行,所以AsyncTask底层实际上是利用到了两个线程池:SerialExecutor和THREAD_POOL_EXECUTOR,前者的内部主要是一个任务队列,它取出一个任务就将其交给THREAD_POOL_EXECUTOR去处理。
HandlerThread
HandlerThread是一种使用了Handler消息机制的Thread,它的具体实现非常简单,就是在run方法中通过Looper.prepare()创建了一个消息队列,并通过Looper.loop()开启消息循环,有了Looper的话就可以在实际使用中创建Handler了。
@Override public void run() { mTid = Process.myTid(); Looper.prepare(); synchronized (this) { mLooper = Looper.myLooper(); notifyAll(); } Process.setThreadPriority(mPriority); onLooperPrepared(); Looper.loop(); mTid = -1; }

由于HandlerThread内部实现实际上是Android消息机制,因此我们要使用HandlerThread时只需要拿到它的Handler并用Handler发送消息即可,我们接着要讲的IntentService内部实现正好就是HandlerThread。
IntentService
IntentService是一种特殊的Service,在IntentService中执行的任务会默认放在子线程中执行,并且由于IntentService继承了Service,是四大组件之一,因此其优先级非常高,比一般的线程更难被系统杀死,因此我们可以将一些非常重要的耗时操作交给IntentService处理。
在启动一个IntentService之前首先会调用onCreate方法:
@Override public void onCreate() { super.onCreate(); HandlerThread thread = new HandlerThread("IntentService[" + mName + "]"); thread.start(); mServiceLooper = thread.getLooper(); mServiceHandler = new ServiceHandler(mServiceLooper); }

可以看到在IntentService的onCreate方法中,首先创建了一个HandlerThread并且让其启动,接着获取到HandlerThread的Looper,并通过Looper获取到了HandlerThread的Handler(这里是特殊的ServiceHandler),有了这个Handler就可以通过消息机制将耗时任务交给HandlerThread处理了。
在每次启动服务的时候系统都会回调onStartCommand()方法:
@Override public int onStartCommand(@Nullable Intent intent, int flags, int startId) { onStart(intent, startId); return mRedelivery ? START_REDELIVER_INTENT : START_NOT_STICKY; }

我们发现onStartCommand内部实际上调用的是onStart方法将外部Intent交给了onStart方法处理,于是我们回到onStart():
@Override public void onStart(@Nullable Intent intent, int startId) { Message msg = mServiceHandler.obtainMessage(); msg.arg1 = startId; msg.obj = intent; mServiceHandler.sendMessage(msg); }

在onStart内部就很简单了,首先得到一个Message,并将intent和id放入Message,通过之前得到的Handler发送将这条消息发送出去就可以了。这里的Intent就是我们外界在startService(intent)时传入的Intent,通过这个Intent就可以解析出外界启动IntentService时传递的参数,通过这些参数就可以区分后台具体要执行什么任务了。
这里我们又会觉得奇怪了,既然我们将消息交给Handler处理了,可是我们之前在学习HandlerThread的时候,发现HandlerThread内部实际上只创建了一个Looper,我们并没有在其中派生Handler的子类并重写handleMessgae()方法,那么到底在哪里处理了消息呢?这里我们需要注意到这里的Handler是ServiceHandler,ServiceHandler是Handler的子类,在ServiceHandler的内部已经帮我们重写了handleMessage()方法:
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); } }

没错,ServiceHandler内部重写的handlerMessage方法帮我们将消息交给了onHandlerIntent来处理,而这个onHandlerIntent方法正是我们在派生IntentService子类的时候要重写的方法!所以最终消息的处理交给了我们自己处理,不得不佩服Android设计人员的聪明才智!

    推荐阅读