当前位置:首页 > > 充电吧
[导读]        作为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。

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

LED驱动电源的输入包括高压工频交流(即市电)、低压直流、高压直流、低压高频交流(如电子变压器的输出)等。

关键字: 驱动电源

在工业自动化蓬勃发展的当下,工业电机作为核心动力设备,其驱动电源的性能直接关系到整个系统的稳定性和可靠性。其中,反电动势抑制与过流保护是驱动电源设计中至关重要的两个环节,集成化方案的设计成为提升电机驱动性能的关键。

关键字: 工业电机 驱动电源

LED 驱动电源作为 LED 照明系统的 “心脏”,其稳定性直接决定了整个照明设备的使用寿命。然而,在实际应用中,LED 驱动电源易损坏的问题却十分常见,不仅增加了维护成本,还影响了用户体验。要解决这一问题,需从设计、生...

关键字: 驱动电源 照明系统 散热

根据LED驱动电源的公式,电感内电流波动大小和电感值成反比,输出纹波和输出电容值成反比。所以加大电感值和输出电容值可以减小纹波。

关键字: LED 设计 驱动电源

电动汽车(EV)作为新能源汽车的重要代表,正逐渐成为全球汽车产业的重要发展方向。电动汽车的核心技术之一是电机驱动控制系统,而绝缘栅双极型晶体管(IGBT)作为电机驱动系统中的关键元件,其性能直接影响到电动汽车的动力性能和...

关键字: 电动汽车 新能源 驱动电源

在现代城市建设中,街道及停车场照明作为基础设施的重要组成部分,其质量和效率直接关系到城市的公共安全、居民生活质量和能源利用效率。随着科技的进步,高亮度白光发光二极管(LED)因其独特的优势逐渐取代传统光源,成为大功率区域...

关键字: 发光二极管 驱动电源 LED

LED通用照明设计工程师会遇到许多挑战,如功率密度、功率因数校正(PFC)、空间受限和可靠性等。

关键字: LED 驱动电源 功率因数校正

在LED照明技术日益普及的今天,LED驱动电源的电磁干扰(EMI)问题成为了一个不可忽视的挑战。电磁干扰不仅会影响LED灯具的正常工作,还可能对周围电子设备造成不利影响,甚至引发系统故障。因此,采取有效的硬件措施来解决L...

关键字: LED照明技术 电磁干扰 驱动电源

开关电源具有效率高的特性,而且开关电源的变压器体积比串联稳压型电源的要小得多,电源电路比较整洁,整机重量也有所下降,所以,现在的LED驱动电源

关键字: LED 驱动电源 开关电源

LED驱动电源是把电源供应转换为特定的电压电流以驱动LED发光的电压转换器,通常情况下:LED驱动电源的输入包括高压工频交流(即市电)、低压直流、高压直流、低压高频交流(如电子变压器的输出)等。

关键字: LED 隧道灯 驱动电源
关闭