AsyncTask(多任務串行/並行)簡單分析

1. 多實例並行時,使用 asynchTask.execute()提交的任務是串行執行的.

下面分析原因:

以下是兩個異步實例提交任務:

  private void asynchTaskTest() {
        // 異步任務1
        TestAnsycTask testAnsycTask1 = new TestAnsycTask();
        Log.e("TAG", "execute1 ThreadName:" + Thread.currentThread().getName());
        testAnsycTask1.execute(new String[]{"111", "2222", "333"});

        // 異步任務2
        TestAnsycTask testAnsycTask2 = new TestAnsycTask();
        Log.e("TAG", "execute2 ThreadName:" + Thread.currentThread().getName());
        testAnsycTask2.execute(new String[]{"aaa", "bbbb", "ccc"});
    }

     private static class TestAnsycTask extends AsyncTask<String, String, String> {

        @Override
        protected String doInBackground(String[] params) {
            Log.e("TestAnsycTask", "doInBackground threadName: " + Thread.currentThread().getName());
            try {
                Thread.sleep(1);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            for (String content : params) {
                Log.e("TestAnsycTask", "  content: " + content);
                if (isCancelled())
                    break;
            }
            return null;
        }
    }

結果顯示任務testAnsycTask1執行完畢後,才執行testAnsycTask2的任務,是串行的

2019-07-12 15:37:01.454 5865-5865/com.pp.sqlitedemo E/TAG: execute1 ThreadName:main
2019-07-12 15:37:01.454 5865-5865/com.pp.sqlitedemo E/TAG: execute2 ThreadName:main
2019-07-12 15:37:01.455 5865-5926/com.pp.sqlitedemo E/TestAnsycTask: doInBackground threadName: AsyncTask #1
2019-07-12 15:37:01.455 5865-5926/com.pp.sqlitedemo E/TestAnsycTask:   content: 111
2019-07-12 15:37:01.455 5865-5926/com.pp.sqlitedemo E/TestAnsycTask:   content: 2222
2019-07-12 15:37:01.455 5865-5926/com.pp.sqlitedemo E/TestAnsycTask:   content: 333
2019-07-12 15:37:01.455 5865-5927/com.pp.sqlitedemo E/TestAnsycTask: doInBackground threadName: AsyncTask #2
2019-07-12 15:37:01.455 5865-5927/com.pp.sqlitedemo E/TestAnsycTask:   content: aaa
2019-07-12 15:37:01.455 5865-5927/com.pp.sqlitedemo E/TestAnsycTask:   content: bbbb
2019-07-12 15:37:01.455 5865-5927/com.pp.sqlitedemo E/TestAnsycTask:   content: ccc

原因:

public class AnsyncTask{

    private static volatile Executor sDefaultExecutor = SERIAL_EXECUTOR;             
    public static final Executor SERIAL_EXECUTOR = new SerialExecutor();

    // 進入 execute(),內部調用的是executeOnExecutor(sDefaultExecutor, params)
    public final AsyncTask<Params, Progress, Result> execute(Params... params{
        return executeOnExecutor(sDefaultExecutor, params);
    }

     // 進入 executeOnExecutor()
     public final AsyncTask<Params, Progress, Result> 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是傳入的 sDefaultExecutor
        exec.execute(mFuture);

        return this;
    }

}

①  進入 execute(),內部調用的是executeOnExecutor(sDefaultExecutor, params)

②進入executeOnExecutor(),可以看到任務是通過傳入的sDefaultExecutor提交的,而sDefaultExecutor是靜態的

 private static volatile Executor sDefaultExecutor = SERIAL_EXECUTOR;             
    public static final Executor SERIAL_EXECUTOR = new SerialExecutor();

因爲sDefaultExecutor是靜態共享的,所以execute()方法提交的任務都緩存到了sDefaultExecutor內部同一個隊列之中,所以是串行執行的

 

那麼如何並行處理任務了?

從Android 3.0開始AsyncTask增加了executeOnExecutor方法,

並行傳入: AsyncTask.THREAD_POOL_EXECUTOR(線程池效果)

串行傳入: AsyncTask.SERIAL_EXECUTOR

並行處理任務,方法如下:

 private void asynchTaskTest() {
        // 異步任務1
        TestAnsycTask testAnsycTask1 = new TestAnsycTask();
        Log.e("TAG", "execute1 ThreadName:" + Thread.currentThread().getName());
//        testAnsycTask1.execute(new String[]{"111", "2222", "333"});
        testAnsycTask1.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, new String[]{"111", "2222", "333"});

        // 異步任務2
        TestAnsycTask testAnsycTask2 = new TestAnsycTask();
        Log.e("TAG", "execute2 ThreadName:" + Thread.currentThread().getName());
//        testAnsycTask2.execute(new String[]{"aaa", "bbbb", "ccc"});
        testAnsycTask2.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, new String[]{"aaa", "bbbb", "ccc"});

    }

結果,並行:

2019-07-12 15:40:44.298 7096-7096/com.pp.sqlitedemo E/TAG: execute1 ThreadName:main
2019-07-12 15:40:44.298 7096-7096/com.pp.sqlitedemo E/TAG: execute2 ThreadName:main
2019-07-12 15:40:44.299 7096-7157/com.pp.sqlitedemo E/TestAnsycTask: doInBackground threadName: AsyncTask #2
2019-07-12 15:40:44.299 7096-7156/com.pp.sqlitedemo E/TestAnsycTask: doInBackground threadName: AsyncTask #1
2019-07-12 15:40:44.339 7096-7157/com.pp.sqlitedemo E/TestAnsycTask:   content: aaa
2019-07-12 15:40:44.339 7096-7156/com.pp.sqlitedemo E/TestAnsycTask:   content: 111
2019-07-12 15:40:44.339 7096-7156/com.pp.sqlitedemo E/TestAnsycTask:   content: 2222
2019-07-12 15:40:44.339 7096-7157/com.pp.sqlitedemo E/TestAnsycTask:   content: bbbb
2019-07-12 15:40:44.339 7096-7156/com.pp.sqlitedemo E/TestAnsycTask:   content: 333
2019-07-12 15:40:44.339 7096-7157/com.pp.sqlitedemo E/TestAnsycTask:   content: ccc

 

 

 

 

 

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章