• 对比一下AsyncTask在子线程和在主线程初始化的区别
      • 在子线程初始化的打印日志
      • 在主线程初始化的打印日志
    • 总结
    • AsyncTask源码

对比一下AsyncTask在子线程和在主线程初始化的区别

public class MainActivity extends AppCompatActivity {    private static final String TAG = MainActivity.class.getCanonicalName();    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_main);        android.util.Log.e(TAG, "#onCreate, " + Thread.currentThread().getName() + "--->" + Thread.currentThread().getId());        new Thread(new Runnable() {            @Override            public void run() {                android.util.Log.e(TAG, "创建AsyncTask的子线程, " + Thread.currentThread().getName() + "--->" + Thread.currentThread().getId());                new AsyncTask() {                    @Override                    protected void onPreExecute() {                        android.util.Log.e(TAG, "子线程内初始化AsyncTask #onPreExecute, " + Thread.currentThread().getName() + "--->" + Thread.currentThread().getId());                        super.onPreExecute();                    }                    @Override                    protected String doInBackground(Void... params) {                        android.util.Log.e(TAG, "子线程内初始化AsyncTask #doInBackground, " + Thread.currentThread().getName() + "--->" + Thread.currentThread().getId());                        return null;                    }                    @Override                    protected void onPostExecute(String result) {                        android.util.Log.e(TAG, "子线程内初始化AsyncTask #onPostExecute, " + Thread.currentThread().getName() + "--->" + Thread.currentThread().getId());                        super.onPostExecute(result);                    }                }.execute((Void) null);            }        }).start();// Caused by: java.util.concurrent.RejectedExecutionException: // Task android.os.AsyncTask$3@7c4920 rejected from  // java.util.concurrent.ThreadPoolExecutor@1f312d9// [Running, pool size = 17, active threads = 17, queued tasks = 128, completed tasks = 0]//        for(int i = 0;i<200;i++) {//            new AsyncTask() {//                @Override//                protected Void doInBackground(Void... params) {//                    // do something//                    try {//                        Thread.sleep(3000);//                    } catch (InterruptedException e) {//                        e.printStackTrace();//                    }//                    return null;//                }//            }.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);//        }        new AsyncTask() {            @Override            protected void onPreExecute() {                android.util.Log.e(TAG, "主线程内初始化AsyncTask #onPreExecute, " + Thread.currentThread().getName() + "--->" + Thread.currentThread().getId());                super.onPreExecute();            }            @Override            protected String doInBackground(Void... params) {                android.util.Log.e(TAG, "主线程内初始化AsyncTask #doInBackground, " + Thread.currentThread().getName() + "--->" + Thread.currentThread().getId());                return null;            }            @Override            protected void onPostExecute(String result) {                android.util.Log.e(TAG, "主线程内初始化AsyncTask #onPostExecute, " + Thread.currentThread().getName() + "--->" + Thread.currentThread().getId());                super.onPostExecute(result);            }        }.execute((Void) null);    }}

在子线程初始化的打印日志:

在主线程初始化的打印日志:

总结:

  • AsyncTask里的Handler为InternalHandler,这里直接使用的主线程的Looper( super(Looper.getMainLooper());),如果去看API 22以下的代码,会发现它没有这个构造函数,而是使用默认的;默认情况下,Handler会使用当前线程的Looper,如果你的AsyncTask是在子线程创建的,那么很不幸,你的onPreExecute和onPostExecute并非在UI线程执行,而是被Handler post到创建它的那个线程执行;如果你在这两个地方更新了UI,那么直接导致崩溃,API 25的代码其实稍微更近一步(通过上面案例日志分析),即使你在子线程中创建AsyncTask,onPostExecute也会在UI线程执行,但是onPreExecute还是在创建AsyncTask的线程中执行
  • 所以 归结为一点:为了避免不必要的麻烦,AsyncTask必须在主线程初始化,源码注释也是这么提示我们的
  • 在Android 1.5刚引入的时候,AsyncTask的execute是串行执行的;到了Android 1.6直到Android 2.3.2,又被修改为并行执行了。Android 3.0以上,AsyncTask默认串行执行的
  • 默认串行的设计是为了避免相同资源的同步访问问题
  • 如果希望AsyncTask可以并行处理的话,可以使用executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR)
  • 如果任务过多,超过了工作队列以及线程数目的限制导致这个线程池发生阻塞,默认的处理方式会直接抛出一个异常导致进程挂掉 如上述案例模拟(当然可以重写AsyncTask,在executeOnExecutor中对exec.execute(mFuture)做保护,捕获RejectedExecutionException异常,这里可以同时做一个统计,如果出现问题,说明AsyncTask不适合这种场景,需要考虑重构,既然知道有此问题,最好主动避免涉及)

AsyncTask源码

这里是以API 25为例进行分析的:

public abstract class AsyncTask<Params, Progress, Result> {    private static final String LOG_TAG = "AsyncTask";    private static final int CPU_COUNT = Runtime.getRuntime().availableProcessors();    // 至少需要2个线程,最多需要4个线程在核心池中    // 可以比CPU数量少一个,避免让所有的CPU都在处理后台工作    // 这个计算方式不同版本表现不一样,早期是CPU+1    private static final int CORE_POOL_SIZE = Math.max(2, Math.min(CPU_COUNT - 1, 4));    private static final int MAXIMUM_POOL_SIZE = CPU_COUNT * 2 + 1;    private static final int KEEP_ALIVE_SECONDS = 30;    // 线程创建工厂    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());        }    };    // 工作队列长度为128    private static final BlockingQueue sPoolWorkQueue =            new LinkedBlockingQueue(128);    // 可以用于并行执行任务的 Executor    public static final Executor THREAD_POOL_EXECUTOR;    // THREAD_POOL_EXECUTOR初始化    static {        ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(                CORE_POOL_SIZE, MAXIMUM_POOL_SIZE, KEEP_ALIVE_SECONDS, TimeUnit.SECONDS,                sPoolWorkQueue, sThreadFactory);        // 核心线程空闲允许超时处理 待遇同非核心线程        threadPoolExecutor.allowCoreThreadTimeOut(true);        THREAD_POOL_EXECUTOR = threadPoolExecutor;    }    // 串行执行任务的Executor(按顺序每次同时只能执行一个任务)    // 指定进程全局有效    public static final Executor SERIAL_EXECUTOR = new SerialExecutor();    private static final int MESSAGE_POST_RESULT = 0x1;    private static final int MESSAGE_POST_PROGRESS = 0x2;    //默认串行执行 而非并行执行    private static volatile Executor sDefaultExecutor = SERIAL_EXECUTOR;    private static InternalHandler sHandler;    private final WorkerRunnable mWorker;    private final FutureTask mFuture;    private volatile Status mStatus = Status.PENDING;    private final AtomicBoolean mCancelled = new AtomicBoolean();    private final AtomicBoolean mTaskInvoked = new AtomicBoolean();    // SERIAL_EXECUTOR也使用THREAD_POOL_EXECUTOR实现的    // 只不过通过队列mTasks调度实现串行的控制    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);            }        }    }    public enum Status {        PENDING,        RUNNING,        FINISHED,    }    private static Handler getHandler() {        synchronized (AsyncTask.class) {            if (sHandler == null) {                sHandler = new InternalHandler();            }            return sHandler;        }    }    /** @hide */    public static void setDefaultExecutor(Executor exec) {        sDefaultExecutor = exec;    }    // 创建一个异步任务,构造函数必须在UI线程调用    public AsyncTask() {        mWorker = new WorkerRunnable() {            public Result call() throws Exception {                mTaskInvoked.set(true);                Result result = null;                try {                    Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);                    //noinspection unchecked                    result = doInBackground(mParams);                    Binder.flushPendingCommands();                } catch (Throwable tr) {                    mCancelled.set(true);                    throw tr;                } finally {                    postResult(result);                }                return result;            }        };        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 occurred while executing doInBackground()",                            e.getCause());                } catch (CancellationException e) {                    postResultIfNotInvoked(null);                }            }        };    }    private void postResultIfNotInvoked(Result result) {        final boolean wasTaskInvoked = mTaskInvoked.get();        if (!wasTaskInvoked) {            postResult(result);        }    }    private Result postResult(Result result) {        @SuppressWarnings("unchecked")        Message message = getHandler().obtainMessage(MESSAGE_POST_RESULT,                new AsyncTaskResult(this, result));        message.sendToTarget();        return result;    }    public final Status getStatus() {        return mStatus;    }    @WorkerThread    protected abstract Result doInBackground(Params... params);    @MainThread    protected void onPreExecute() {    }    @SuppressWarnings({"UnusedDeclaration"})    @MainThread    protected void onPostExecute(Result result) {    }    @SuppressWarnings({"UnusedDeclaration"})    @MainThread    protected void onProgressUpdate(Progress... values) {    }    @SuppressWarnings({"UnusedParameters"})    @MainThread    protected void onCancelled(Result result) {        onCancelled();    }        @MainThread    protected void onCancelled() {    }    public final boolean isCancelled() {        return mCancelled.get();    }    public final boolean cancel(boolean mayInterruptIfRunning) {        mCancelled.set(true);        return mFuture.cancel(mayInterruptIfRunning);    }    public final Result get() throws InterruptedException, ExecutionException {        return mFuture.get();    }    public final Result get(long timeout, TimeUnit unit) throws InterruptedException,            ExecutionException, TimeoutException {        return mFuture.get(timeout, unit);    }     // 基于指定参数执行任务 默认串行执行    @MainThread    public final AsyncTask execute(Params... params) {        return executeOnExecutor(sDefaultExecutor, params);    }    //基于指定参数执行任务,可以自定义Executor,也可以直接使用THREAD_POOL_EXECUTOR    @MainThread    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();        mWorker.mParams = params;        exec.execute(mFuture);        return this;    }    //简易版 可以直接执行一个Runnable对象    @MainThread    public static void execute(Runnable runnable) {        sDefaultExecutor.execute(runnable);    }    @WorkerThread    protected final void publishProgress(Progress... values) {        if (!isCancelled()) {            getHandler().obtainMessage(MESSAGE_POST_PROGRESS,                    new AsyncTaskResult(this, values)).sendToTarget();        }    }    private void finish(Result result) {        if (isCancelled()) {            onCancelled(result);        } else {            onPostExecute(result);        }        mStatus = Status.FINISHED;    }    private static class InternalHandler extends Handler {        public InternalHandler() {            super(Looper.getMainLooper());        }        @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;            }        }    }    private static abstract class WorkerRunnable<Params, Result> implements Callable<Result> {        Params[] mParams;    }    @SuppressWarnings({"RawUseOfParameterizedType"})    private static class AsyncTaskResult<Data> {        final AsyncTask mTask;        final Data[] mData;        AsyncTaskResult(AsyncTask task, Data... data) {            mTask = task;            mData = data;        }    }}

点击一下 有惊喜

更多相关文章

  1. Handler机制详述1---Handler的简介和用法
  2. Android(安卓)Service之串行化Service:IntentService(系列3)
  3. Android使用libgdx实现模拟方向键控制角色移动的方法
  4. android开发 零碎知识
  5. Android出现java.lang.RuntimeException: Can‘t toast on a thr
  6. Android未调用Looper.prepare()-Can't create handler inside th
  7. Android仿微信底部按钮滑动变色
  8. Android(安卓)- Binder驱动
  9. Android(安卓)Audio System 之二: AudioFlinger

随机推荐

  1. Android中不规则形状View的布局实现
  2. [随便写写]Android基础教程
  3. Android开发之旅:应用程序基础及组件
  4. Android(安卓)adb环境配置
  5. android handler总结
  6. Android统计图表MPAndroidChart:为多条统
  7. andorid handler 消息传递机制
  8. 如何使用Mindjet Maps for Android中的移
  9. Google Cloud Messaging (Android(安卓)
  10. android:Layout_weight正确的理解