简单介绍:

       在操作系统中,线程是系统所能调用的最小单元,同时线程是一种受限的系统资源,因此不可能无限制的产生,并且线程的创建和销毁都会有相应的开销,试想一下,如果在一个进程中频繁的创建和销毁线程,势必会产生内存的抖动,显然这不是高效的做法,那么正确的做法就是采用线程池,通过线程池可以避免因为频繁创建和销毁带来的系统开销,android线程来源于java,因此主要也是通过Executor来派生特定类型的线程池。不同种类的线程池又具有各自的特性。

线程种类:

除了Thread之外,在android可以扮演线程角色的还有很对,例如AsyncTask,IntentService以及HandlerThread,HandlerThread是一种特殊的线程,虽然AsyncTask,IntentService以及HandlerThread有别于Thread,但是他们的本质仍然是线程。对于AsyncTask而言,它的底层用到了线程池,对于IntentService和HandlerThread,他们的底层直接使用了线程。

使用场景:

      AsyncTask封装了线程池和handler,他主要方便开发者在子线程中更新UI。

      HandlerThread是具有消息循环的线程,在它的内部可以使用handler

     IntentService是一个服务,系统对它进行了封装,是它更方便处理后台任务,其实它的内部采用HandlerThread执行任务,当任务执行完成后IntentService会自动退出。从任务执行的角度看,IntentService很像一个后台线程,但他又是一个服务,由于service不容易被系统杀死从而可以尽量保证任务的执行。

AsyncTask:

    AsyncTask是一种轻量级的异步任务类,它可以在线程池中执行后台任务,然后把执行的进度和最终的结果传递给主线程并在主线程中更新UI,从实现上来说,AsyncTask封装了Thread和Handler,通过它可以更加方便的执行后台任务并在主线程中更新ui,但是AsyncTask并不适合进行特病耗时的任务,对于特别耗时的任务的任务建议采用线程池。

   AsyncTask是一个抽象的泛型类,它提供了Params,Progress,Result等三个泛型参数,其中params表示参数的类型,progress表示后台任务执行的进度,而Result表示后台任务执行完成返回结果的类型,如果不传递参数,那么这个三个泛型可以使用Void来代替,下面看下AsyncTask的声明:

public abstract class AsyncTask<Params, Progress, Result>

AsyncTask有四个核心方法,他们的含义如下所示:

onPreExecute() : 当主线程执行异步方法之前调用,用于准备工作,例如显示加载对话框

doInBackground(Param... params) : 此方法在线程池中执行,此方法用于异步任务的执行,其中Params代码参数类型,Params... 表示参数是可变长度,其实就相当于数组,此方法的参数类型就是execute(Param... params)传入的,此方法通过调用publishProgress更新任务的进度,同时publishProgress会调用onProgressUpdate()方法。此方法返回的结果将作为onPostExecute()的参数。

onProgressUpdate(Progress... values) :更新任务执行的进度

onPostExecute(Result result):在主线程中执行,在异步执行完成之后,此方法会被调用,其中Result参数是后台任务返回的结果,即doInBackground的返回值。

这几个方法的执行顺序是:首先执行onPreExecute(),然后doInBackground在后台执行,执行的过程中通过onProgressUpdate更新执行任务的进度,最后任务执行完毕回调onPostExecute(),当然,除了以上四个方法之外,还有一个onCancelled()方法,此方法在异步取消时被调用,这个时候onPostExecute就不会被调用。

下面我们实例化一个AsyncTask的实例:

public void test(){
        String url = "wwww.baidu.com";
        AsyncTask asyncTask = new DownloaderAsyncTask();
        asyncTask.execute(url);

    }

    class  DownloaderAsyncTask extends AsyncTask<String,Integer,String>{

        @Override
        protected String doInBackground(String... params) {
            return null;//后台任务执行
        }
        @Override
        protected void onPreExecute() {
            super.onPreExecute();//准备工作,如显示加载提示框
        }

        @Override
        protected void onProgressUpdate(Integer[] values) {
            super.onProgressUpdate(values);//后台任务进度更新
        }

        @Override
        protected void onPostExecute(String o) {
            super.onPostExecute(o);//后台执行完成执行,并将结果作为参数返回,如果后台任务取消就会回调onCancelled(),此方法不回调。
        }
    }

AsyncTask在具体的过程中也有一些限制的,主要有一下几点:

1、AsyncTask 类补习在主线程中加载

2、AsyncTask的对象必须在主线程中创建

3、execute方法必须在UI线程调用

4、不要在程序中调用onPreExecute(),doInBackground(),onProgressUpdate,onPostExecute方法

5、AsyncTask对象只能执行一次,

6、在Android 1.6之前,AsyncTask是串行执行任务的,Android1.6的时候采用线程池处理并行任务,但是Android3.0为了避免AsyncTask并发的错误,AsyncTask又采用一个线程串行执行任务,尽管如此,3.0以后我们可以调用executeOnExecutor()方法来并行执行任务。

AsyncTask的工作原理:

为了分析AsyncTask的工作原理,我们从execute方法开始分析,execute方法又调用executorOnExecutor()方法,他们的实现如下所示:

@MainThread
    public final AsyncTask<Params, Progress, Result> execute(Params... params) {
        return executeOnExecutor(sDefaultExecutor, params);
    }

    /**
     * Executes the task with the specified parameters. The task returns
     * itself (this) so that the caller can keep a reference to it.
     * 
     * <p>This method is typically used with {@link #THREAD_POOL_EXECUTOR} to
     * allow multiple tasks to run in parallel on a pool of threads managed by
     * AsyncTask, however you can also use your own {@link Executor} for custom
     * behavior.
     * 
     * <p><em>Warning:</em> Allowing multiple tasks to run in parallel from
     * a thread pool is generally <em>not</em> what one wants, because the order
     * of their operation is not defined.  For example, if these tasks are used
     * to modify any state in common (such as writing a file due to a button click),
     * there are no guarantees on the order of the modifications.
     * Without careful work it is possible in rare cases for the newer version
     * of the data to be over-written by an older one, leading to obscure data
     * loss and stability issues.  Such changes are best
     * executed in serial; to guarantee such work is serialized regardless of
     * platform version you can use this function with {@link #SERIAL_EXECUTOR}.
     *
     * <p>This method must be invoked on the UI thread.
     *
     * @param exec The executor to use.  {@link #THREAD_POOL_EXECUTOR} is available as a
     *              convenient process-wide thread pool for tasks that are loosely coupled.
     * @param params The parameters of the task.
     *
     * @return This instance of AsyncTask.
     *
     * @throws IllegalStateException If {@link #getStatus()} returns either
     *         {@link AsyncTask.Status#RUNNING} or {@link AsyncTask.Status#FINISHED}.
     *
     * @see #execute(Object[])
     */
    @MainThread
    public final AsyncTask<Params, Progress, Result> 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;
    }

上面的代码中,sDefaultExecutor实际是一个串行的线程池,一个进程中所有的AsyncTask全部在这个串行的线程池中排队执行,在executeOnExecutor方法中,Asynctask的onPreExecute方法最先执行,然后线程池开始执行,下面分析线程池的执行的过程,如下所示:

public static final Executor SERIAL_EXECUTOR = new SerialExecutor();
    private static volatile Executor sDefaultExecutor = SERIAL_EXECUTOR;
    private static class SerialExecutor implements Executor{
        final ArrayDeque<Runnable> mTasks = new ArrayDeque<>();
        Runnable mActive;

        @Override
        public void execute(@NonNull final Runnable command) {
            mTasks .offer(new Runnable() {
                @Override
                public void run() {
                    command.run();
                    scheduleNext();
                }
            });
            if(mActive != null){
                scheduleNext();
            }
        }

        private void scheduleNext() {
            if((mActive = mTasks.poll()) != null){
                THREAD_PO0L_EXECUTOR.executor(mActive);
            }
        }
    }



从SerialExecutor的实现可以分析AsyncTask的排队执行的过程,首先系统会把AsyncTask的Params的参数封装成FutureTask对象,FutureTask是一个并发类,在这里充当了Runnable的作用,接着FutureTask会交给SerialExecutor的execute方法去处理,SerialExecutor的execute方法会把FutureTask对象插入到任务栈mTasks中,如果这个时候没有正在活动的AsyncTask任务,那么就会调用scheduleNext执行了下一个任务直到最后一个任务都被执行完成为止,从这点可以看出Asynctask是串行执行。

AsyncTask有两个线程池(SerialExecutor和THREAD_POOL_EXECUTOR)和一个Handler(InternalHandler),其中线程池SerialExecutor用于任务的排队,而线程池THREAD_POOL_EXECUTOR用于真正执行任务,InternalHandler用于将执行环境从线程池切换到主线程,在AsyncTask的构造方法有如下代码,由于FutureTask的run方法会调用mWorker的call方法,因此mWorker的call方法最终会在线程池中执行:

mWorkerRunnable = new WorkRunnable<Params,Result>(){
            public Result Call() throws Exception{
                mTaskInvoked.set(true);
                Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
                return postResult(doInBackground(Params));
            }
        }
private Result postResult(Result result) {
        @SuppressWarnings("unchecked")
        Message message = getHandler().obtainMessage(MESSAGE_POST_RESULT,
                new AsyncTaskResult<Result>(this, result));
        message.sendToTarget();
        return result;
    }
private static class InternalHandler extends Handler {
        public InternalHandler(Looper looper) {
            super(looper);
        }

        @SuppressWarnings({"unchecked", "RawUseOfParameterizedType"})
        @Override
        public void handleMessage(Message msg) {
            AsyncTaskResult<?> result = (AsyncTaskResult<?>) msg.obj;
            switch (msg.what) {
                case MESSAGE_POST_RESULT:
                    // There is only one result
                    result.mTask.finish(result.mData[0]);
                    break;
                case MESSAGE_POST_PROGRESS:
                    result.mTask.onProgressUpdate(result.mData);
                    break;
            }
        }
    }

finish方法中的逻辑也比较简单,如果AsyncTask被取消执行了,那么就调用onCancelled(),否则调用onPostExecute(),可以看到doInBackground的返回结果传递给onPostExecute方法。


HandlerThread:

HandlerThread继承了Thread,他是一种可以使用Handler的Thread,它的实现也很简单,就是在run方法中通过Looper.prepare()来创建消息队列,并通过Looper.loop()来开启消息循环,HandlerThread的run方法如下所示:

@Override
    public void run() {
        mTid = Process.myTid();
        Looper.prepare();
        synchronized (this) {
            mLooper = Looper.myLooper();
            notifyAll();
        }
        Process.setThreadPriority(mPriority);
        onLooperPrepared();
        Looper.loop();
        mTid = -1;
    }

它和普通Thread的不同,普通Thread主要用于在run方法中执行一个耗时任务,而HandlerThread在内部创建一个消息队列,外界需要通过Handler消息方式通知HandlerThread执行一个具体的任务,由于HandlerThread的run方法是一个无限循环,因此当明确不需要使用HandlerThread时,可以通过quit或者quitSafely方法来终止线程执行,这是一个良好的编程习惯。


IntentService:

  IntentService是一个特殊的Service,他继承了Service并且是一个抽象类,因此必须创建子类才能使用IntentService,IntentService可用于执行后台耗时任务,当任务执行后它会自动停止,IntentService因为是Service,所以优先级比较高,不容易被后台杀死,实际上,IntentService封装了HandlerThread和Handler,这一点可以在onCreate方法中看出:

@Override
    public void run() {
        mTid = Process.myTid();
        Looper.prepare();
        synchronized (this) {
            mLooper = Looper.myLooper();
            notifyAll();
        }
        Process.setThreadPriority(mPriority);
        onLooperPrepared();
        Looper.loop();
        mTid = -1;
    }

当IntentService被第一次启动时,它的onCreate()方法会被调用,onCreate()方法会创建一个HandlerThread,然后使用Looper创建一个Handler对象mServiceHandler,这样通过mServiceHandler发送的消息最终会在HandlerThread中执行,IntentService执行后台任务,每次启动都会调用onStartCommand(),然后在onstartCommand()中调用onStart(),onstart()如下所示:

@Override
    public void onStart(@Nullable Intent intent, int startId) {
        Message msg = mServiceHandler.obtainMessage();
        msg.arg1 = startId;
        msg.obj = intent;
        mServiceHandler.sendMessage(msg);
    }
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);
        }
    }

onlHandleIntent方法是一个抽象方法,他需要我们在子类中实现,它的作用是从Intent参数中区分具体的任务并执行这些任务,那么在onHandlerIntent方法执行完成这个任务后,stopSelf(int startId)就会直接停止服务,如果目前存在多个后台任务,那么当onHandIntent方法执行最后一个任务时,stopSelf(int stratId)才会直接停止服务,