AsyncTask Android的线程和线程池

Android中的线程
在Android中扮演线程的角色除了Thread外还有AsyncTask 还有IntentService,同时HandlerThread也是特殊的一种线程。尽管AsyncTask、IntentService以及HandlerThread的表现形式都有别于传统的线程,但是它们的本质仍然是传统的线程。对于AsyncTask来说,它的底层用到了线程池,对于IntentService和HandlerThread来说,它们的底层则直接使用了线程。

不同形式的线程虽然都是线程,但是它们仍具有不同的特性与使用场景。AsyncTask封装了线程池和Handler,它主要是为了方便开发者在子线程更新UI。HandlerThread是一种具有消息循环的线程,在它的内部可以使用Handler。IntentService是一个服务,系统对其进行了封装使其可以更方便的执行后台任务,IntentService内部采用了HandlerThread来执行任务,当任务执行完毕后IntentService会自动退出。从任务执行的角度来看,IntentService的作用很像一个后台线程,但是IntentService是一种服务,它不容易被系统杀死从而可以尽量保证任务的执行,而如果是一个后台线程,由于这个时候进程中没有活动的四大组件,那么这个进程的优先级就会非常低,会很容易被系统杀死,这就是IntentService的有点。

在操作系统中,线程是操作系统调度的最小单元,同时线程又是一种受限的系统资源,即线程不可能无限制地产生,并且线程的创建和销毁都会有相应的开销。当系统中存在大量的线程时,系统会通过时间片轮转的方式调度每个线程,因此线程不可能做到绝对的并行,除非线程数量小于等于cpu的核心数,一般来说这是不可能的。试想一下,如果在一个进程中频繁的创建和销毁线程,这显然不是高效的做法。正确的做法是采用线程池,一个线程池中会缓存一定数量的线程,通过线程池就可以避免因为频繁创建和销毁线程所带来的系统开销。Android中的线程池来源于Java,主要通过Executor来派生特定类型的线程池,不同种类的线程池又具有各自的特性。

1.AsyncTask

AsyncTask是一种轻量级的异步任务类,它可以在线程池中执行后台任务,然后把执行的进度和最终的结果传递给主线程并在主线程中更新UI。从实现上来说,AsyncTask封装了Thread和Handler,通过AsyncTask可以更加方便地执行后台任务以及在主线程中访问UI,但是AsyncTask并不适合进行特别耗时的后台任务,对于特别耗时的任务来说,建议使用线程池。
AsyncTask是一个抽象的泛型类,它提供了Params、Progress和Result这三个泛型类参数

AsyncTask提供了4个核心的方法,他们的含义分别是:
1.onPreExecute(),在主线程中执行,在异步任务执行之前,此方法会被调用,一般可以用于做一些准备工作。
2.doInBackground(Params…params),在线程池中执行,此方法用于执行异步任务,params参数表示异步任务的输入参数。在此方法中可以通过publishProgress()方法来更新任务进度,publishProgress()方法会调用onProgressUpdate()方法。另外此方法需要返回计算结果给onPostExecute()方法。
3.onProgressUpdate(Progress…values),在主线程中执行,在异步任务执行之后,此方法会被调用,其中result参数是在后台任务的返回值,即doInbackground的返回值。
4.onPostExecute(Result result),在主线程执行,在异步任务执行之后,此方法会被调用,其中result参数是后台任务的返回值,即doInBackground的返回值。

AsyncTask在具体使用过程中也是有一些条件限制的,主要有如下几点:
1.AsyncTask的类必须在主线程中加载,这就意味着第一次访问AsyncTask必须发生在主线程,当然这个过程在Android4.1及以上的版本以及被系统自动完成了。
2.AsyncTask的对象必须在主线程中创建。
3.execute方法必须在主线程调用,
4.不要再程序中直接调用onPreExecute()、onPostExecute()、doInBackground和onProgressUpdate()方法。
5.一个AsyncTask对象只能执行一次,即只能调用一次execute方法,否则会报运行时异常。
6.在Android1.6之前,AsyncTask是串行执行任务,Android1.6的时候AsyncTask开始采用线程池里处理并行任务,但是从Android3.0开始,为了避免AsyncTask所带来的并发错误,AsyncTask又采用一个线程来串行执行任务。尽管如此,在Android3.0以后及后续的版本,我们仍然可以通过AsyncTask的executeOnExecutor方法来并行地执行任务。

为了分析AsyncTask的工作原理,我们从它的execute方法开始分析,execute方法会调用executeOnExecute方法如下:

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>();
        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();
            }
        }
@MainThread
    public final AsyncTask<Params, Progress, Result> execute(Params... params) {
        return executeOnExecutor(sDefaultExecutor, params);
    }

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

AsyncTask中有两个线程池(SerialExecute和THREAD_POOL_EXECUTE)和一个Handler(InternalHandler),其中线程池SerialExecute用于任务的排队而我们的THREAD_POOL_EXECUTE用于正在地执行任务,InternalHandler用于将执行环境从线程池切换到主线程。

需要注意的一点我们知道Android3.0以前它是串行起来的,但是到Android3.0后新增了executeOnExecute方法,这个方法不能再低于3.0版本上使用,使用这个方法我们可以使AsyncTask并行起来。

HandlerThread工作原理
HandlerThread集成了Thread,它是一种可以使用Handler的Thread,它的实现也很简单,就是在run方法通过Looper.prepare()来创建消息队列,并通过Looper.loop()来开启消息循环,由于它是一个无限循环,我们在不使用的时候可以通过quit或者quitSafely来终止线程。

IntentService工作原理
IntentService可用于执行后台耗时的任务,当任务执行完它会自动停止,由于IntentSerice是服务的原因,这导致它的优先级比单纯的线程要高很多,因为它的游侠你高所以不被系统杀死,IntentService封装了HandlerThread和Handler。

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值