1. 程式人生 > >Android原始碼分析—帶你認識不一樣的AsyncTask(串並行)

Android原始碼分析—帶你認識不一樣的AsyncTask(串並行)

前言

什麼是AsyncTask,相信搞過android開發的朋友們都不陌生。AsyncTask內部封裝了Thread和Handler,可以讓我們在後臺進行計算並且把計算的結果及時更新到UI上,而這些正是Thread+Handler所做的事情,沒錯,AsyncTask的作用就是簡化Thread+Handler,讓我們能夠通過更少的程式碼來完成一樣的功能,這裡,我要說明的是:AsyncTask只是簡化Thread+Handler而不是替代,實際上它也替代不了。同時,AsyncTask從最開始到現在已經經過了幾次程式碼修改,任務的執行邏輯慢慢地發生了改變,並不是大家所想象的那樣:AsyncTask是完全並行執行的就像多個執行緒一樣,其實不是的,所以用AsyncTask的時候還是要注意,下面會一一說明。另外本文主要是分析AsyncTask的原始碼以及使用時候的一些注意事項,如果你還不熟悉AsyncTask,請先閱讀

這裡先給出AsyncTask的一個例子:

  1. privateclass DownloadFilesTask extends AsyncTask<URL, Integer, Long> {  
  2.      protected Long doInBackground(URL... urls) {  
  3.          int count = urls.length;  
  4.          long totalSize = 0;  
  5.          for (int i = 0; i < count; i++) {  
  6.              totalSize += Downloader.downloadFile(urls[i]);  
  7.              publishProgress((int) ((i / (float) count) * 100));  
  8.              // Escape early if cancel() is called
  9.              if (isCancelled()) break;  
  10.          }  
  11.          return totalSize;  
  12.      }  
  13.      protectedvoid onProgressUpdate(Integer... progress) {  
  14.          setProgressPercent(progress[0
    ]);  
  15.      }  
  16.      protectedvoid onPostExecute(Long result) {  
  17.          showDialog("Downloaded " + result + " bytes");  
  18.      }  
  19.  }  

使用AsyncTask的規則

  • AsyncTask的類必須在UI執行緒載入(從4.1開始系統會幫我們自動完成)
  • AsyncTask物件必須在UI執行緒建立
  • execute方法必須在UI執行緒呼叫
  • 不要在你的程式中去直接呼叫onPreExecute(), onPostExecute, doInBackground, onProgressUpdate方法
  • 一個AsyncTask物件只能執行一次,即只能呼叫一次execute方法,否則會報執行時異常
  • AsyncTask不是被設計為處理耗時操作的,耗時上限為幾秒鐘,如果要做長耗時操作,強烈建議你使用Executor,ThreadPoolExecutor以及FutureTask
  • 在1.6之前,AsyncTask是序列執行任務的,1.6的時候AsyncTask開始採用執行緒池裡處理並行任務,但是從3.0開始,為了避免AsyncTask所帶來的併發錯誤,AsyncTask又採用一個執行緒來序列執行任務

AsyncTask到底是序列還是並行?

給大家做一下實驗,請看如下實驗程式碼:程式碼很簡單,就是點選按鈕的時候同時執行5個AsyncTask,每個AsyncTask休眠3s,同時把每個AsyncTask執行結束的時間打印出來,這樣我們就能觀察出到底是序列執行還是並行執行。

  1. @Override
  2. publicvoid onClick(View v) {  
  3.     if (v == mButton) {  
  4.         new MyAsyncTask("AsyncTask#1").execute("");  
  5.         new MyAsyncTask("AsyncTask#2").execute("");  
  6.         new MyAsyncTask("AsyncTask#3").execute("");  
  7.         new MyAsyncTask("AsyncTask#4").execute("");  
  8.         new MyAsyncTask("AsyncTask#5").execute("");  
  9.     }  
  10. }  
  11. privatestaticclass MyAsyncTask extends AsyncTask<String, Integer, String> {  
  12.     private String mName = "AsyncTask";  
  13.     public MyAsyncTask(String name) {  
  14.         super();  
  15.         mName = name;  
  16.     }  
  17.     @Override
  18.     protected String doInBackground(String... params) {  
  19.         try {  
  20.             Thread.sleep(3000);  
  21.         } catch (InterruptedException e) {  
  22.             e.printStackTrace();  
  23.         }  
  24.         return mName;  
  25.     }  
  26.     @Override
  27.     protectedvoid onPostExecute(String result) {  
  28.         super.onPostExecute(result);  
  29.         SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");  
  30.         Log.e(TAG, result + "execute finish at " + df.format(new Date()));  
  31.     }  
  32. }  
我找了2個手機,系統分別是4.1.1和2.3.3,按照我前面的描述,AsyncTask在4.1.1應該是序列的,在2.3.3應該是並行的,到底是不是這樣呢?請看Log

Android 4.1.1上執行:從下面Log可以看出,5個AsyncTask共耗時15s且時間間隔為3s,很顯然是序列執行的


Android 2.3.3上執行:從下面Log可以看出,5個AsyncTask的結束時間是一樣的,很顯然是並行執行


結論:從上面的兩個Log可以看出,我前面的描述是完全正確的。下面請看原始碼,讓我們去了解下其中的原理。

原始碼分析

  1. /* 
  2.  * Copyright (C) 2008 The Android Open Source Project 
  3.  * 
  4.  * Licensed under the Apache License, Version 2.0 (the "License"); 
  5.  * you may not use this file except in compliance with the License. 
  6.  * You may obtain a copy of the License at 
  7.  * 
  8.  *      http://www.apache.org/licenses/LICENSE-2.0 
  9.  * 
  10.  * Unless required by applicable law or agreed to in writing, software 
  11.  * distributed under the License is distributed on an "AS IS" BASIS, 
  12.  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
  13.  * See the License for the specific language governing permissions and 
  14.  * limitations under the License. 
  15.  */
  16. package android.os;  
  17. import java.util.ArrayDeque;  
  18. import java.util.concurrent.BlockingQueue;  
  19. import java.util.concurrent.Callable;  
  20. import java.util.concurrent.CancellationException;  
  21. import java.util.concurrent.Executor;  
  22. import java.util.concurrent.ExecutionException;  
  23. import java.util.concurrent.FutureTask;  
  24. import java.util.concurrent.LinkedBlockingQueue;  
  25. import java.util.concurrent.ThreadFactory;  
  26. import java.util.concurrent.ThreadPoolExecutor;  
  27. import java.util.concurrent.TimeUnit;  
  28. import java.util.concurrent.TimeoutException;  
  29. import java.util.concurrent.atomic.AtomicBoolean;  
  30. import java.util.concurrent.atomic.AtomicInteger;  
  31. publicabstractclass AsyncTask<Params, Progress, Result> {  
  32.     privatestaticfinal String LOG_TAG = "AsyncTask";  
  33.     //獲取當前的cpu核心數
  34.     privatestaticfinalint CPU_COUNT = Runtime.getRuntime().availableProcessors();  
  35.     //執行緒池核心容量
  36.     privatestaticfinalint CORE_POOL_SIZE = CPU_COUNT + 1;  
  37.     //執行緒池最大容量
  38.     privatestaticfinalint MAXIMUM_POOL_SIZE = CPU_COUNT * 2 + 1;  
  39.     //過剩的空閒執行緒的存活時間
  40. 相關推薦

    Android原始碼分析認識一樣AsyncTask(並行)

    前言 什麼是AsyncTask,相信搞過android開發的朋友們都不陌生。AsyncTask內部封裝了Thread和Handler,可以讓我們在後臺進行計算並且把計算的結果及時更新到UI上,而這些正是Thread+Handler所做的事情,沒錯,AsyncTask

    CSS並不簡單--認識一樣的漸變

    這篇文章主要分享CSS3中linear-gradient和radial-gradient的知識,帶給大家使用漸變的另一個角度。 一、線性漸變 這裡需要大家先去看一下基本語法,再看接下來的例子。 linear-gradient(90d

    從D&G事件,認識靠譜的義大利!

    從D&G事件,帶你認識不靠譜的義大利! 一. D&G大秀本將如期舉行,但其設計師卻對中國人肆無忌憚公然辱罵,引起了惡劣後果。 此事曝光後,迅速引爆網路,娛樂圈眾明星紛紛表態拒絕出席晚宴,迪麗熱巴和王俊凱終止與D&G合作。輿論一片譁然,紛紛喊出讓這個牌子滾出中國。

    壓敏電阻選型,瞭解一樣的VDR

    壓敏電阻選型,帶您瞭解不一樣的VDR   壓敏電阻(英文簡稱VDR),看上去,是一個陌生又很專業的東西,但是,在我們的日常生活中,卻隨處可見,比如在家用電器、汽車電子系統、電源系統、安防系統、電動機保護、浪湧抑制器等領域都能捕捉到其身影。電路保護元器件壓敏電阻的應用,一般都不在明

    Just Waiting for You!個性化推薦領略一樣的演算法之美

    2016年,SDCC·中國軟體開發者大會相繼走進了上海、深圳、成都、杭州各地。11月18日-20日將在北京完美收官,屆時年度最受歡迎的企業、講師將在這裡齊聚一堂,約百位講師將圍繞電商架構、程式語言、前端開發、微信開發、視訊直播、推薦演算法、Spark實踐等方面,

    [原始碼分析] 梳理 Flink SQL / Table API內部執行流程

    # [原始碼分析] 帶你梳理 Flink SQL / Table API內部執行流程 [Toc] ## 0x00 摘要 本文將簡述Flink SQL / Table API的內部實現,為大家把 "從SQL語句到具體執行" 這個流程串起來。並且儘量多提供呼叫棧,這樣大家在遇到問題時就知道應該從什麼地方設定

    Android:手把手分析 Protocol Buffer使用 原始碼

    前言 習慣用 Json、XML 資料儲存格式的你們,相信大多都沒聽過Protocol Buffer Protocol Buffer 其實 是 Google出品的一種輕量 & 高效的結構化資料儲存格式,效能比 Json、XML 真的強!太!多!

    還有人認識通訊詐騙,短信驗證碼認識一下

    col 手機號 jpg 數據庫 平臺 獲取 gsm信號 第三方服務 關鍵技術 首先進行一下自我介紹,短信驗證碼本碼。短信驗證碼:網站或者客戶端應用需要接入短信驗證碼(手機驗證碼)的功能,可以實現註冊用戶的手機號碼正確性校驗,確保用戶填寫的手機號碼的真實性。現在已經完全融入了

    Android原始碼分析之為什麼在onCreate() 和 onResume() 獲取到 View 的寬高

    轉載自:https://www.jianshu.com/p/d7ab114ac1f7 先來看一段很熟悉的程式碼,可能在最開始接觸安卓的時候,大部分人都寫過的一段程式碼;即嘗試在 onCreate() 和 onResume() 方法中去獲取某個 View 的寬高資訊: 但是列印輸出後,我們會發

    Android:手把手 深入讀懂 Retrofit 2.0 原始碼

    前言 在Android開發中,網路請求十分常用 而在Android網路請求庫中,Retrofit是當下最熱的一個網路請求庫 Github截圖 今天,我將手把手帶你深入剖析Retrofit v2.0的原始碼,希望你們會喜歡 請儘量在PC端

    Android:手把手深入剖析 Retrofit 2.0 原始碼

    前言 在Andrroid開發中,網路請求十分常用 而在Android網路請求庫中,Retrofit是當下最熱的一個網路請求庫 今天,我將手把手帶你深入剖析Retrofit v2.0的原始碼,希望你們會喜歡 目錄 1. 簡介

    解讀Google官方SwipeRefreshLayout控制元件原始碼揭祕Android下拉重新整理的實現原理

    前言 想必大家也發現,時下的很多App都應用了這個Google出品的SwipeRefreshLayout下拉重新整理控制元件,它以Material Design風格、適用場景廣泛,簡單易用等特性而獨步江湖。但在我們使用的過程中,不可避免地會發現一些bug,或者

    30多個Android 開發者工具 開發帶

    desc 模擬 演示 數據 實時 拼寫檢查 速度 plugin div 文中部分工具是收費的,但是絕大多數都是免費的。 FlowUp 這是一個幫助你跟蹤app整體性能的工具,深入分析關鍵的性能數據如FPS, 內存, CPU, 磁盤, 等等。FlowUp根據用戶數量收費。

    七夕 美中給一個一樣的情人節

    孕媽 七夕 情人節迢迢牽牛星,皎皎河漢女,纖纖擢素手,劄劄弄機杼....”傳古至今,數不盡的詩詞歌賦描寫了唯美浪漫的七夕節,一年一度的七夕就要到了,是時候給單身汪撒上一波狗糧啦~   都說孩子上輩子是父母的情人,準爸爸、孕媽媽們更是因為有了寶寶而心情激動,和“小情人”有說不盡的情話、道不盡的溫柔,迫不

    智慧商場,給顧客一樣的體驗

    人性 包括 智能 體驗 手機 其中 在線 硬件 有效 數據顯示,在雙十一當天阿裏巴巴旗下各平臺總交易額達到1682億元,其中無線占比達到90%。當今是電商高速發展的時代,實體店受到了空前的打擊。這個時代,數據資產與智能硬件顯得無比重要,借助智能的商業系統,智慧商場開始受到越

    老司機認識IP一些基礎的知識

    對與IP簡單的認識入門對IP得一個簡單認識ip地址 ip address 作用: 標識一個節點的網絡地址! 地址組成{點分十進制}:-一共分為32個二位進制-轉換為4個十位進制表示,以. 隔開 子網掩碼:是用來區分網絡位和主機位的 網關 是指一個網絡連接到另外一個網絡的關口 備用配置1專用的ip地址:1

    認識ButterKnife

    原文連結:http://blog.csdn.net/donkor_/article/details/77879630 前言: ButterKnife是一個專注於Android系統的View注入框架,以前總是要寫很多findViewById來找到View物件,有了ButterKnife可以很輕鬆的

    到處都在說的一對一視訊直播原始碼瞭解真人一對一按分鐘計費陪聊模式+cps

    直播如此火爆的關鍵,就在於其特別強大的引流能力,因此,當直播人盡皆知,人人蔘與,直播的內容領域,也隨之擴充套件、細分。直播已不止是網紅主播和娛樂平臺的漲粉創收利器,對企業而言,它已是必須把握的巨大商機。 隨著直播平臺受到越來越多使用者的關注,直播的功能和形式也越來越多樣化,作為創業者來說,人人都想在這個網際

    Android原始碼分析-Activity的啟動過程

    分享一下我老師大神的人工智慧教程!零基礎,通俗易懂!http://blog.csdn.net/jiangjunshow 也歡迎大家轉載本篇文章。分享知識,造福人民,實現我們中華民族偉大復興!        

    Android原始碼分析-全面理解Context

    分享一下我老師大神的人工智慧教程!零基礎,通俗易懂!http://blog.csdn.net/jiangjunshow 也歡迎大家轉載本篇文章。分享知識,造福人民,實現我們中華民族偉大復興!