zoukankan      html  css  js  c++  java
  • 大约Android 3.0后AsyncTask默认的单线程分析

    在Android下了很大的后台操作在需要的情况下。通常用于AsyncTask这个类。比方说,网络负载形象。访问server接口。一般的情况是使用一个的一例AsyncTask对象mTask,复制AsyncTask抽象方法doinBackgroud等等,最后运行task.execute(params),然后就能够在UI线程上方便的取得后台线程的运行结果;

    AsyncTask运行中终于触发的是把任务交给线池THREAD_POOL_EXECUTOR来运行,提交的任务并行的在线程池中运行。但这些规则在3.0之后发生了变化,3.0之后提交的任务是串行运行的。运行完一个任务才运行下一个!

    先看看3.0曾经的代码;

    private static final int CORE_POOL_SIZE = 5;
    private static final int MAXIMUM_POOL_SIZE = 128;
    private static final int KEEP_ALIVE = 10;
    </pre><p></p><pre>
    public static final Executor THREAD_POOL_EXECUTOR = new ThreadPoolExecutor(CORE_POOL_SIZE, MAXIMUM_POOL_SIZE, KEEP_ALIVE,TimeUnit.SECONDS, sPoolWorkQueue, sThreadFactory);

    3.0曾经线程池里核心线程有5个,同一时候存在的线程数最大不能超过128个。线程池里的线程都是并行执行的。


    可是在3.0之后,直接调用execute(params)触发的是sDefaultExecutor的execute(runnable)方法。而不是原来的THREAD_POOL_EXECUTOR

    private static final int CORE_POOL_SIZE = CPU_COUNT + 1;
    private static final int MAXIMUM_POOL_SIZE = CPU_COUNT * 2 + 1;
    private static final int KEEP_ALIVE = 1;

    public static void execute(Runnable runnable) {
            sDefaultExecutor.execute(runnable);
        }

    看看这个sDefaultExecutor与原来的THREAD_POOL_EXECUTOR线程池有什么 区别,sDefaultExecutor实际上是指向SerialExecutor的一个实例,从名字上看是一个顺序运行的executor;

    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();
                }
            }
    
            protected synchronized void scheduleNext() {
                if ((mActive = mTasks.poll()) != null) {
                    THREAD_POOL_EXECUTOR.execute(mActive);
                }
            }
        }

    分析SerialExecutor,当提交一个任务。运行一次execute(),向mTasks加入一个runnable。此时mActive为null。接着会运行scheduleNext(),将mActive指向刚刚加入的runbale,并提交到THREAD_POOL_EXECUTOR中运行,接着就线程池中就会运行以下这段代码。

    try {
                            r.run();
                        } finally {
                            scheduleNext();
                        }

    当asyncTask提交大量的任务时。会反复之前的流程。任务都加入至mTasks中了,提交第一个任务之后,mActive便不再为Null了,之后的任务假设要被运行就必需等到前一个任务run方法跑完,也就是try{ }语句块中的run(),前一个任务运行完后,才会调用finally
    后面的scheduleNext()从mTasks中取出下一个任务来运行。


    分析完上面的代码后,如今对于3.0以后AsyncTask默认情况下同一时候仅仅存在一个线程顺序运行的原理就了解清楚了;


    假设想要提交的任务在能并行运行呢?这在网络图片显示中还是比較实用的;

    AsyncTask也为我们提供了第二种启动方法

    public final AsyncTask<Params, Progress, Result> executeOnExecutor(Executor exec,Params... params)

    这里能够指定自己定义的executor,而不再用SerialExecutor,假设乐意的话当然也能够直接使用用原本的THREAD_POOL_EXECUTOR,这样就能够保证多个任务并行运行了




    版权声明:本文博客原创文章,博客,未经同意,不得转载。

  • 相关阅读:
    git简单使用
    简单Spring和mybatis整合配置文件
    ASP.NET程序开发范例宝典
    C# DataSet和DataTable详解
    AOP
    匿名内部类
    数据库事务
    mybatis
    线程池
    单例模式
  • 原文地址:https://www.cnblogs.com/mengfanrong/p/4640824.html
Copyright © 2011-2022 走看看