AsyncTask與多任務

問題由來

? ? ?之前看到一篇博文,說AsyncTask不適合運行多任務, 多個任務不會異步執行, 當時只是印象里記住了一下也不確定, 今天把代碼看了看, 把原因寫出來。

?

問題的代碼演示

?

 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函數    
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里打印出來的結果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不適合運行多任務"這個推斷, 另一個有趣的結果是非異步執行的時候居然可能不是在一個線程里運行的【看我上面用紅色標記的部分】。

?

分析:

?

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的并發編程的話就知道sDefaultExecutor用于將要完成的任務交給內部已經實現的線程池去執行(有興趣的話可以去看看Doug Lea寫的那本《Java并發編程》)

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一起執行時序列化執行而被異步的了,?

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

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

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

?

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

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, 所以這里線程池的線程數就可能是[2, 3]了, 然而對于AsyncTask來說1就夠了, 多余1的線程其實是沒有什么幫助的。

?

P.S.

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

? ? ?

轉載于:https://www.cnblogs.com/sabo/p/5040685.html

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/257957.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/257957.shtml
英文地址,請注明出處:http://en.pswp.cn/news/257957.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

iptables簡單應用

可以修改/etc/rc.d/boot.local讓規則重啟后也能生效&#xff0c;如&#xff1a;/sbin/iptables -F/sbin/iptables -A INPUT -i eth0 -p tcp --sport 80 -j ACCEPT/sbin/iptables -A INPUT -i eth0 -p tcp -j DROP/sbin/iptables -A INPUT -i eth0 -p udp -j DROPiptables是一個…

linux中內部命令有哪些,linux內部命令有哪些

linux中常見的內部命令有&#xff1a;1.exit命令&#xff0c;退出當前的shell&#xff1b;2.history命令&#xff0c;顯示歷史執行過的命令&#xff1b;3.cd命令&#xff0c;切換當前工作目錄&#xff1b;4.source命令&#xff0c;重新執行剛修改的初始化文件&#xff1b;5.ech…

使用SALT-API進入集成開發的簡單樣例

測試的時候&#xff0c;可以CURL -K&#xff0c;但真正作集成的時候&#xff0c;卻是不可以的。 必須&#xff0c;不可以讓TOKEN滿天飛吧。 現在進入這個階段了。寫個樣例先&#xff1a; import salt import salt.auth import salt.log import saltapiopts salt.client.LocalC…

POJ 2778

題意&#xff1a;很Uva項鏈題目類似。 區別&#xff1a; 1、字符串很多&#xff0c;用map hash超時&#xff0c;用Trie查找。 2、DFS判斷連通&#xff0c;和并查集判連通&#xff0c;被我寫錯的地方時&#xff0c;查森林的時候&#xff0c;還是要Find_Set。 1 #include <ios…

linux掛載VMFS硬盤,ESX4.1掛載NFS共享存儲(VMkernel)

要使用vmotion,iscsi,nfs功能&#xff0c;必須啟用VMkernel端口&#xff0c;ESX 4.1默認不啟用&#xff0c;ESXi 5.x默認啟用。在 vCenter Server“SZVCENTER01”上調用對象“datastoreSystem-44”的“HostDatastoreSystem.CreateNasDatastore” 失敗。掛載NFS存儲的ESX控制臺命…

Perl學習之四:語句(續)

循環控制&#xff1a;1.last 退出標簽的語句塊2.next 3.redo不推薦&#xff0c;循環次數不可控 4.goto不推薦。***************************************標簽&#xff1a; 先定義一個 labellast|next|redo|goto label&#xff1b; last VS next 相當于C語言中的&#xff1a;las…

2017年8個最流行的Web編程趨勢

互聯網一直在不斷的發展&#xff0c;這意味著開發人員必須及時了解當前的所有變化。人們在新聞、社交、購物到銀行等各大方面都與互聯網有著千絲萬縷的聯系。因此&#xff0c;為了滿足全球數百萬網絡用戶的需求&#xff0c;Web開發需求正在上升。Web編程趨勢是在W開發的過程中不…

linux 分卷壓縮到指定目錄,運用在android下Linux分卷壓縮與分卷解壓的命令

protected static Vector execRootCmd(String paramString) {Vector localVector new Vector();try {Process localProcess Runtime.getRuntime().exec("su ");// 經過Root處理的android系統即有su命令OutputStream localOutputStream localProcess.getOutputStre…

gRPC-rs:從 C 到 Rust

介紹 在上篇文章中&#xff0c;我們講到 TiKV 為了支持 [gRPC]&#xff0c;我們造了個輪子 [gRPC-rs]&#xff0c;這篇文章簡要地介紹一下這個庫。首先我們來聊聊什么是 gRPC。gRPC 是 Google 推出的基于 [HTTP2] 的開源 RPC 框架&#xff0c;希望通過它使得各種微服務之間擁有…

紅帽linux無法進入tty,linux自啟腳本(以及無法進入tty控制臺)

1.建立需開機運行的腳本auto(可以不要后面的.sh后綴)2.放在/etc/init.d/目錄下 (操作系統復制命令&#xff0c;在當前文件夾下復制sudo cp auto /etc/init.d)[可能先要對init.d取得x權限]3.賦予權限&#xff0c;在init.d文件目錄下sudo chmod 775 ./auto4.執行&#xff0c;命…

【最短路】SDUT3034--炸學校

炸學校 Time Limit: 2000ms Memory limit: 65536K 有疑問&#xff1f;點這里^_^ 題目描述 “小兒么小二郎&#xff0c;背著那炸彈炸學校&#xff0c;不怕那太陽曬&#xff0c;也不怕那風雨狂。”估計這首歌我們大家都耳熟能詳了。于是就有一群小學生們商量著炸學校。要把本…

管控研發部門USB設備

前提背景&#xff1a;研發部門圖紙經常泄漏&#xff0c;領導說要管控USB,但是要能讀&#xff0c;只限制不能寫。本想大力推薦Devicelock&#xff0c;因費用原因沒了后話&#xff0c;只好使用最基本的域策略進行實施.51CTOblog傳圖片這么麻煩&#xff0c;還是全部寫文字好了。實…

linux系統編程練手項目,精選 22 個 C++ 項目,編程小白練手首選!

C/C 做為元老級的編程語言&#xff0c;任時光更迭依舊屹立不倒&#xff0c;哪怕現在煊赫一時的AI&#xff0c;其底層也是用其編寫。linux那么做為新手該如何快速上手 C 呢&#xff1f;固然是敲代碼啊&#xff01;一切不寫代碼的學編程都是瞎搞。下面為你們精選了 22 個 C 項目&…

Swift iOS : WebView緩存圖片的方法

廣告 Swift iOS開發小書 &#xff0c;幫你快速上手開發 www.ituring.com.cn/book/2413 正文 每次加載WebView內容&#xff0c;如果圖片可以緩存的話&#xff0c;速度就會非常快。默認情況下&#xff0c;WebView自己來加載圖片&#xff0c;緩存的策略也是自己定的。如想要自己緩…

linux怎么同時查看兩個文件,MultiTail - 在單個Linux終端中同時監視多個文件

無論是服務器管理員還是程序員&#xff0c;我們需要參考多個日志文件來有效地排除故障任務。 為了實現這一點&#xff0c;我們必須打開&#xff0c;拖尾或更少的不同shell中的每個日志文件。 但是&#xff0c;我們可以使用傳統的tail命令狀尾-f在/ var / log / messages文件或尾…

新一代藍牙5標準開啟 會成為物聯網的最佳選擇嗎

在過去&#xff0c;藍牙在生活中最常見的應用就是鍵盤、鼠標、音箱和藍牙耳機&#xff0c;這些傳輸對頻寬要求不高&#xff0c;藍牙技術的采用不僅節省了線材成本&#xff0c;還增加了產品的靈活性。藍牙技術聯盟(SIG)正式宣布推出新一代標準藍牙5(Bluetooth 5)&#xff0c;其主…

今日BBC

1、隨身英語 Dry January 新年戒酒一個月 link 2、地道英語 Hot potato 棘手的問題“燙手山芋” link 3、今日新聞 Brussels attacks: Belgian police arrest six suspects link The arrests were made in the Schaerbeek district. There is no word yet on the identitie…

c語言中的指針語法,C語言中指針的用法介紹

C語言中指針的用法介紹for(int i0;i{num*s;s;}return num;)這個例子中的函數 fun統計一個字符串中各個字符的 ASCII 碼值之和。前面說了&#xff0c;數組的名字也是一個指針。在函數調用中&#xff0c;當把 str 作為實參傳遞給形參 s后&#xff0c;實際是把 str 的值傳遞給了 s…

實驗吧 貌似有點難 偽造ip

解題鏈接&#xff1a; http://ctf5.shiyanbar.com/phpaudit/ 解答&#xff1a; 點擊View the source code —>代碼顯示IP為1.1.1.1即可得到KEY—>使用modify header偽造IP—>拿到flag 相關&#xff1a; modify header我也是第一次用&#xff0c;下面附上相關說明&…

用C語言用指針怎么算通用定積分,C語言:利用指針編寫程序,用梯形法計算給定的定積分實例...

題目要求利用指針編寫程序&#xff0c;用梯形法計算下列公式中的定積分&#xff1a;參考代碼首先說明一下指針的用處&#xff1a;因為所傳遞的參數均為數字&#xff0c;并不需要使用指針提高效率&#xff0c;故這里使用指針指向函數。請注意calc()函數中的這一語句&#xff1a;…