当前位置:首页 > 芯闻号 > 充电吧
[导读]        作为Android中最常用跨线程手段之一,AsyncTask经常出现在代码中。我也经常使用AsyncTask,有一次遇到一个奇怪的情况:AsyncTask.execute()函数调用后

        作为Android中最常用跨线程手段之一,AsyncTask经常出现在代码中。我也经常使用AsyncTask,有一次遇到一个奇怪的情况:AsyncTask.execute()函数调用后,AsyncTask却未立即执行,而是过了一段时间以后,才开始执行,当时觉得很奇怪,一番Google后,得知是线程池的原因。事后也一直搁着,直到今天工作有点空,花了点时间看看AsyncTask的实现。

AsyncTask的线程池

        AsyncTask提供了两个线程池,用以执行后台任务:

        当然,开发者也可以通过自定义线程池来执行后台任务:



THREAD_POOL_EXECUTOR

        THREAD_POOL_EXECUTOR的定义为:

    /**
     * An {@link Executor} that can be used to execute tasks in parallel.
     */
    public static final Executor THREAD_POOL_EXECUTOR
            = new ThreadPoolExecutor(CORE_POOL_SIZE, MAXIMUM_POOL_SIZE, KEEP_ALIVE,
                    TimeUnit.SECONDS, sPoolWorkQueue, sThreadFactory);
        其中用到的一些参数如下:

    private static final int CORE_POOL_SIZE = 5;
    private static final int MAXIMUM_POOL_SIZE = 128;
    private static final int KEEP_ALIVE = 1;

    private static final ThreadFactory sThreadFactory = new ThreadFactory() {
        private final AtomicInteger mCount = new AtomicInteger(1);

        public Thread newThread(Runnable r) {
            return new Thread(r, "AsyncTask #" + mCount.getAndIncrement());//创建一个拥有特定名字的线程
        }
    };

    private static final BlockingQueue sPoolWorkQueue =
            new LinkedBlockingQueue(10);
        这里不详细解释ThreadPoolExecutor的实现,而是简单介绍下ThreadPoolExecutor的工作逻辑(线程池的工作逻辑,相信大家都比较清楚)

当线程池内无空闲线程,且线程数不足CORE_POOL_SIZE时,创建新的线程来执行任务。当线程池内无空闲线程,且线程数大于等于CORE_POOL_SIZE,且sPoolWorkQueue为满时,把任务放到sPoolWorkQueue中。当线程池内无空闲线程,且线程数大于等于CORE_POOL_SZIE,且sPoolWorkQueue已满,且线程数未达到MAXIMUM_POOL_SIZE时,创建新线程以执行任务。当线程池内无空闲线程,且线程数大于等于CORE_POOL_SZIE,且sPoolWorkQueue已满,且线程数等于MAXIMUM_POOL_SIZE时,抛出异常。

       从当前的参数我们可以看到,THREAD_POOL_EXECUTOR最多同时拥有128个线程执行任务,通常情况下(sPoolWorkQueue有任务,且未满),THREAD_POOL_EXECUTOR会拥有5条线程同时处理任务。


SERIAL_EXECUTOR

        默认情况下,AsyncTask会在SERIAL_EXECUTOR中执行后台任务(其实,这个说法不太准确,稍后解释):

    private static volatile Executor sDefaultExecutor = SERIAL_EXECUTOR;        
        SERIAL_EXECUTOR的定义为:

    /**
     * An {@link Executor} that executes tasks one at a time in serial
     * order.  This serialization is global to a particular process.
     */
    public static final Executor SERIAL_EXECUTOR = new SerialExecutor();

        而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并不是一个线程池(所以本文前面说AsyncTask的两个线程池的说法是不准确的),它实际上是提供了一个mTask来储存所有待执行的task,并逐个提交给THREAD_POOL_EXECUTOR执行。
       所以,实际上所有的后台任务都是在THREAD_POOL_EXECUTOR中执行的,而
AsyncTask.execute()
        和
AsyncTask.executorOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR)
        的差别在于,前者会逐个执行任务,同一时间仅有一个任务被执行。

AsyncTask的实现

        AsyncTask的实现,需要依赖于两个成员:

    private final WorkerRunnable mWorker;
    private final FutureTask mFuture;

WorkerRunnable

        WorkerRunnable的定义为:

    private static abstract class WorkerRunnable implements Callable {
        Params[] mParams;
    }
        而Callable的定义为:

public interface Callable {
    /**
     * Computes a result, or throws an exception if unable to do so.
     *
     * @return computed result
     * @throws Exception if unable to compute a result
     */
    V call() throws Exception;
}
         WorkerRunnable为抽象类,所以使用的其实是它的子类:

   /**
     * Creates a new asynchronous task. This constructor must be invoked on the UI thread.
     */
    public AsyncTask() {
        mWorker = new WorkerRunnable() {
            public Result call() throws Exception {
                mTaskInvoked.set(true);

                Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
                //noinspection unchecked
                return postResult(doInBackground(mParams));
            }
        };

        mFuture = new FutureTask(mWorker) {
            @Override
            protected void done() {
                try {
                    postResultIfNotInvoked(get());
                } catch (InterruptedException e) {
                    android.util.Log.w(LOG_TAG, e);
                } catch (ExecutionException e) {
                    throw new RuntimeException("An error occured while executing doInBackground()",
                            e.getCause());
                } catch (CancellationException e) {
                    postResultIfNotInvoked(null);
                }
            }
        };
    }

         call函数的重载挺简单,主要就是调用doInBackground函数,执行后台任务。


FutureTask

        FutureTask的实现比WorkerRunnable复杂,但是,如果抓住核心去分析也很简单。

        首先, FutureTask实现了RunnableFuture接口:

public class FutureTask implements RunnableFuture {
        然后,RunnableFuture继承自Runnable:
public interface RunnableFuture extends Runnable, Future {
    /**
     * Sets this Future to the result of its computation
     * unless it has been cancelled.
     */
    void run();
}
        所以,FutureTask类,肯定实现了run方法:
   public void run() {
        if (state != NEW ||
            !UNSAFE.compareAndSwapObject(this, runnerOffset,
                                         null, Thread.currentThread()))
            return;
        try {
            Callable c = callable;
            if (c != null && state == NEW) {
                V result;
                boolean ran;
                try {
                    result = c.call();
                    ran = true;
                } catch (Throwable ex) {
                    result = null;
                    ran = false;
                    setException(ex);
                }
                if (ran)
                    set(result);
            }
        } finally {
            // runner must be non-null until state is settled to
            // prevent concurrent calls to run()
            runner = null;
            // state must be re-read after nulling runner to prevent
            // leaked interrupts
            int s = state;
            if (s >= INTERRUPTING)
                handlePossibleCancellationInterrupt(s);
        }
    }
        忽略其他处理,run函数执行了callable的call函数。再说说callable是什么东西:
    public FutureTask(Callable callable) {
        if (callable == null)
            throw new NullPointerException();
        this.callable = callable;
        this.state = NEW;       // ensure visibility of callable
    }
      在看看前面已经介绍过的AsyncTask构造函数:
  /**
     * Creates a new asynchronous task. This constructor must be invoked on the UI thread.
     */
    public AsyncTask() {
        mWorker = new WorkerRunnable() {
            public Result call() throws Exception {
                mTaskInvoked.set(true);

                Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
                //noinspection unchecked
                return postResult(doInBackground(mParams));
            }
        };

        mFuture = new FutureTask(mWorker) {
            @Override
            protected void done() {
                try {
                    postResultIfNotInvoked(get());
                } catch (InterruptedException e) {
                    android.util.Log.w(LOG_TAG, e);
                } catch (ExecutionException e) {
                    throw new RuntimeException("An error occured while executing doInBackground()",
                            e.getCause());
                } catch (CancellationException e) {
                    postResultIfNotInvoked(null);
                }
            }
        };
    }
       原来callable就是mWorker,也就是说,FutureTask的run函数,会调用doInBackground函数。

AsyncTask.execute函数的执行过程        1. AsyncTask.execute
    public final AsyncTask execute(Params... params) {
        return executeOnExecutor(sDefaultExecutor, params);
    }
       2.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();//调用onPreExecute

        mWorker.mParams = params;//保存参数
        exec.execute(mFuture);//执行task

        return this;
    }
        跳过SERIAL_EXECUTOR和THREAD_POOL_EXECUTOR的实现不谈,我们可以用如下的方式,简单理解exe.execute函数:
void execute(Runnable runnable){
    new Thread(runnable).start();
}
        3. FutureTask.run()
   public void run() {
        if (state != NEW ||
            !UNSAFE.compareAndSwapObject(this, runnerOffset,
                                         null, Thread.currentThread()))
            return;
        try {
            Callable c = callable;
            if (c != null && state == NEW) {
                V result;
                boolean ran;
                try {
                    result = c.call();
                    ran = true;
                } catch (Throwable ex) {
                    result = null;
                    ran = false;
                    setException(ex);
                }
                if (ran)
                    set(result);
            }
        } finally {
            // runner must be non-null until state is settled to
            // prevent concurrent calls to run()
            runner = null;
            // state must be re-read after nulling runner to prevent
            // leaked interrupts
            int s = state;
            if (s >= INTERRUPTING)
                handlePossibleCancellationInterrupt(s);
        }
    }
         前面已经讲过,会调用mWorker.call().
         4. WorkerRunnable.call()
 mWorker = new WorkerRunnable() {
            public Result call() throws Exception {
                mTaskInvoked.set(true);

                Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
                //noinspection unchecked
                return postResult(doInBackground(mParams));
            }
        };
          5. AsyncTask.postResult()
    private Result postResult(Result result) {
        @SuppressWarnings("unchecked")
        Message message = sHandler.obtainMessage(MESSAGE_POST_RESULT,
                new AsyncTaskResult(this, result));
        message.sendToTarget();
        return result;
    }
         通过sHandler,去UI线程执行接下来的工作。
        6. sHandler.handleMessage
    private static class InternalHandler extends Handler {
        @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;
            }
        }
    }
        7. AsyncTask.finish
    private void finish(Result result) {
        if (isCancelled()) {
            onCancelled(result);
        } else {
            onPostExecute(result);
        }
        mStatus = Status.FINISHED;
    }
        通常情况下(即尚未调用过cancel(boolean interrupt)),isCannelled()为false,接下来会执行onPostExecute。

总结

       从本质上来讲,AsyncTask即为Execute和Handler的组合。AsyncTask利用Executor在后台线程中执行doInBackgroud函数,并利用handler执行onPostExecute函数。

       而AsyncTask的行为则由executeOnExecutor函数中参数exec决定。AsyncTask提供的SERIAL_EXECUTOR限定任务逐个执行,而THREAD_POOL_EXECUTOR支持最多128个任务并行执行,但是当待处理任务过多时,会抛出RejectedExecutionException。

本站声明: 本文章由作者或相关机构授权发布,目的在于传递更多信息,并不代表本站赞同其观点,本站亦不保证或承诺内容真实性等。需要转载请联系该专栏作者,如若文章内容侵犯您的权益,请及时联系本站删除。
换一批
延伸阅读

9月2日消息,不造车的华为或将催生出更大的独角兽公司,随着阿维塔和赛力斯的入局,华为引望愈发显得引人瞩目。

关键字: 阿维塔 塞力斯 华为

加利福尼亚州圣克拉拉县2024年8月30日 /美通社/ -- 数字化转型技术解决方案公司Trianz今天宣布,该公司与Amazon Web Services (AWS)签订了...

关键字: AWS AN BSP 数字化

伦敦2024年8月29日 /美通社/ -- 英国汽车技术公司SODA.Auto推出其旗舰产品SODA V,这是全球首款涵盖汽车工程师从创意到认证的所有需求的工具,可用于创建软件定义汽车。 SODA V工具的开发耗时1.5...

关键字: 汽车 人工智能 智能驱动 BSP

北京2024年8月28日 /美通社/ -- 越来越多用户希望企业业务能7×24不间断运行,同时企业却面临越来越多业务中断的风险,如企业系统复杂性的增加,频繁的功能更新和发布等。如何确保业务连续性,提升韧性,成...

关键字: 亚马逊 解密 控制平面 BSP

8月30日消息,据媒体报道,腾讯和网易近期正在缩减他们对日本游戏市场的投资。

关键字: 腾讯 编码器 CPU

8月28日消息,今天上午,2024中国国际大数据产业博览会开幕式在贵阳举行,华为董事、质量流程IT总裁陶景文发表了演讲。

关键字: 华为 12nm EDA 半导体

8月28日消息,在2024中国国际大数据产业博览会上,华为常务董事、华为云CEO张平安发表演讲称,数字世界的话语权最终是由生态的繁荣决定的。

关键字: 华为 12nm 手机 卫星通信

要点: 有效应对环境变化,经营业绩稳中有升 落实提质增效举措,毛利润率延续升势 战略布局成效显著,战新业务引领增长 以科技创新为引领,提升企业核心竞争力 坚持高质量发展策略,塑强核心竞争优势...

关键字: 通信 BSP 电信运营商 数字经济

北京2024年8月27日 /美通社/ -- 8月21日,由中央广播电视总台与中国电影电视技术学会联合牵头组建的NVI技术创新联盟在BIRTV2024超高清全产业链发展研讨会上宣布正式成立。 活动现场 NVI技术创新联...

关键字: VI 传输协议 音频 BSP

北京2024年8月27日 /美通社/ -- 在8月23日举办的2024年长三角生态绿色一体化发展示范区联合招商会上,软通动力信息技术(集团)股份有限公司(以下简称"软通动力")与长三角投资(上海)有限...

关键字: BSP 信息技术
关闭
关闭