日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

AsyncTask与多任务

發(fā)布時間:2023/12/13 编程问答 33 豆豆
生活随笔 收集整理的這篇文章主要介紹了 AsyncTask与多任务 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

問題由來

? ? ?之前看到一篇博文,說AsyncTask不適合運行多任務(wù), 多個任務(wù)不會異步執(zhí)行, 當(dāng)時只是印象里記住了一下也不確定, 今天把代碼看了看, 把原因?qū)懗鰜怼?/span>

?

問題的代碼演示

?

1 public class AsyncTaskDemo extends AsyncTask<String, Integer, String>{ 2 private final static String TAG = "AsyncTaskTest"; 3 4 @Override 5 protected String doInBackground(String... params) { 6 Log.v(TAG, params[0] + "=================doInBackground===================PID = " + Thread.currentThread().getId()); 7 8 return params[0]; 9 } 10 11 12 }

?

1 // 一個按鈕的onclick函數(shù) 2 public void test(View view) { 3 Log.v("AsyncTaskTest", "CPU_COUNT = " + Runtime.getRuntime().availableProcessors()); 4 5 new AsyncTaskDemo().execute("Hello1"); 6 new AsyncTaskDemo().execute("Hello2"); 7 new AsyncTaskDemo().execute("Hello3"); 8 new AsyncTaskDemo().execute("Hello4"); 9 } //logcat里打印出來的結(jié)果12-11 16:07:34.865 1979-1979/com.sabo.helloworld V/AsyncTaskTest﹕ CPU_COUNT = 1 12-11 16:07:34.871 1979-2102/com.sabo.helloworld V/AsyncTaskTest﹕ Hello1=================doInBackground===================PID = 161 12-11 16:07:34.872 1979-2103/com.sabo.helloworld V/AsyncTaskTest﹕ Hello2=================doInBackground===================PID = 162 12-11 16:07:34.872 1979-2103/com.sabo.helloworld V/AsyncTaskTest﹕ Hello3=================doInBackground===================PID = 162 12-11 16:07:34.872 1979-2103/com.sabo.helloworld V/AsyncTaskTest﹕ Hello4=================doInBackground===================PID = 162

實驗大致輔證了"AsyncTask不適合運行多任務(wù)"這個推斷, 另一個有趣的結(jié)果是非異步執(zhí)行的時候居然可能不是在一個線程里運行的【看我上面用紅色標(biāo)記的部分】。

?

分析:

?

1 @MainThread 2 public final AsyncTask<Params, Progress, Result> execute(Params... params) { 3 return executeOnExecutor(sDefaultExecutor, params); 4 }

?

@MainThreadpublic 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.execute(mFuture);// exec --> sDefaultExecutorreturn this;}

如果熟悉Java的并發(fā)編程的話就知道sDefaultExecutor用于將要完成的任務(wù)交給內(nèi)部已經(jīng)實現(xiàn)的線程池去執(zhí)行(有興趣的話可以去看看Doug Lea寫的那本《Java并發(fā)編程》)

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);}}}

這里的代碼就能解釋為什么多個AsyncTask一起執(zhí)行時序列化執(zhí)行而被異步的了,?

1 new AsyncTaskDemo().execute("Hello1"); //mActive == null 2 new AsyncTaskDemo().execute("Hello2"); //mActive != null 3 new AsyncTaskDemo().execute("Hello3"); //mActive != null 4 new AsyncTaskDemo().execute("Hello4"); //mActive != null

上面紅色標(biāo)記的代碼可以看出,只有第一個任務(wù)直接調(diào)用scheduleNext()--->THREAD_POOL_EXECUTOR.execute(mActive), 線程池直接將任務(wù)交由線程去執(zhí)行,而后面幾個任務(wù)先被放入ArrayDeque<Runnable> mTasks, 沒有交給任何線程去執(zhí)行,

每個任務(wù)執(zhí)行完之后又都要運行上面綠顏色標(biāo)記的scheduleNext(), 從而依次序序列化執(zhí)行任務(wù)。

?

上面提到的有趣的事情,既然AsyncTask是序列化執(zhí)行任務(wù)的, 那么線程池里只要一個線程就能滿足要求了啊, 為什么會有兩個線程。

1 private static final int CORE_POOL_SIZE = CPU_COUNT + 1; 2 private static final int MAXIMUM_POOL_SIZE = CPU_COUNT * 2 + 1; 3 private static final int KEEP_ALIVE = 1; 4 5 public static final Executor THREAD_POOL_EXECUTOR 6 = new ThreadPoolExecutor(CORE_POOL_SIZE, MAXIMUM_POOL_SIZE, KEEP_ALIVE, 7 TimeUnit.SECONDS, sPoolWorkQueue, sThreadFactory);

上面我把CPU_COUNT的值打印出來是1, 所以這里線程池的線程數(shù)就可能是[2, 3]了, 然而對于AsyncTask來說1就夠了, 多余1的線程其實是沒有什么幫助的。

?

P.S.

:-)第一次寫博客, 加上功力又有限, 歡迎大家指正canbin.zhang#qq.com

? ? ?

轉(zhuǎn)載于:https://www.cnblogs.com/sabo/p/5040685.html

總結(jié)

以上是生活随笔為你收集整理的AsyncTask与多任务的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。