導航:首頁 > 操作系統 > android多線程多任務下載

android多線程多任務下載

發布時間:2023-01-04 10:35:40

『壹』 android多線程的四種方式:Handler、AsyncTask、ThreadPoolExector、IntentService

     非同步通信機制,將工作線程中需更新UI的操作信息 傳遞到 UI主線程,從而實現 工作線程對UI的更新處理,最終實現非同步消息的處理。Handler不僅僅能將子線程的數據傳遞給主線程,它能實現任意兩個線程的數據傳遞。

(1)Message

    Message 可以在線程之間傳遞消息。可以在它的內部攜帶少量數據,用於在不同線程之間進行數據交換。除了 what 欄位,還可以使用 arg1 和 arg2 來攜帶整型數據,使用 obj 來攜帶 Object 數據。

(2) Handler

    Handler 作為處理中心,用於發送(sendMessage 系列方法)與處理消息(handleMessage 方法)。

(3) MessageQueue

    MessageQueue 用於存放所有通過 Handler 發送的消息。這部分消息會一直存放在消息隊列中,直到被處理。每個線程中只會有一個 MessageQueue 對象

(4) Looper

    Looper 用於管理 MessageQueue 隊列,Looper對象通過loop()方法開啟了一個死循環——for (;;){},不斷地從looper內的MessageQueue中取出Message,並傳遞到 Handler 的 handleMessage() 方法中。每個線程中只會有一個 Looper 對象。

    AsyncTask 是一種輕量級的任務非同步類,可以在後檯子線程執行任務,且將執行進度及執行結果傳遞給 UI 線程。

(1)onPreExecute()

    在 UI 線程上工作,在任務執行 doInBackground() 之前調用。此步驟通常用於設置任務,例如在用戶界面中顯示進度條。

(2)doInBackground(Params... params)

    在子線程中工作,在 onPreExecute() 方法結束後執行,這一步被用於在後台執行長時間的任務,Params 參數通過 execute(Params) 方法被傳遞到此方法中。任務執行結束後,將結果傳遞給 onPostExecute(Result) 方法,同時我們可以通過 publishProgress(Progress) 方法,將執行進度發送給 onProgressUpdate(Progress) 方法。

(3)onProgressUpdate(Progress... values)

    在 UI 線程上工作,會在 doInBackground() 中調用 publishProgress(Progress) 方法後執行,此方法用於在後台計算仍在執行時(也就是 doInBackgound() 還在執行時)將計算執行進度通過 UI 顯示出來。例如,可以通過動畫進度條或顯示文本欄位中的日誌,從而方便用戶知道後台任務執行的進度。

(4)onPostExecute(Result result)

    在 UI 線程上工作,在任務執行完畢(即 doInBackground(Result) 執行完畢)並將執行結果傳過來的時候工作。

使用規則:

(1)AsyncTask 是個抽象類,所以要創建它的子類實現抽象方法

(1)AsyncTask 類必須是在 UI 線程中被載入,但在Android 4.1(API 16)開始,就能被自動載入完成。

(2)AsyncTask 類的實例對象必須在 UI 線程中被創建。

(3)execute() 方法必須是在 UI 線程中被調用。

(4)不要手動調用方法 onPreExecute()、onPostExecute()、doInBackground()、onProgressUpdate()

(5)任務只能執行一次(如果嘗試第二次執行,將拋出異常)。即一個AsyncTask對象只能調用一次execute()方法。

原理:

          其源碼中原理還是 Thread 與 Handler 的實現,其包含 兩個線程池,一個 Handler,如下所示:

名稱類型作用

SERIAL_EXECUTOR線程池分發任務,串列分發,一次只分發一個任務

THREAD_POOL_EXECUTOR線程池執行任務,並行執行,執行的任務由 SERIAL_EXECUTOR 分發

InternalHandlerHandler負責子線程與主線程的溝通,通知主線程做 UI 工作

    一方面減少了每個並行任務獨自建立線程的開銷,另一方面可以管理多個並發線程的公共資源,從而提高了多線程的效率。所以ThreadPoolExecutor比較適合一組任務的執行。Executors利用工廠模式對ThreadPoolExecutor進行了封裝。

Executors提供了四種創建ExecutorService的方法,他們的使用場景如下:

1. Executors.newFixedThreadPool()

    創建一個定長的線程池,每提交一個任務就創建一個線程,直到達到池的最大長度,這時線程池會保持長度不再變化。

當線程處於空閑狀態時,它們並不會被回收,除非線程池被關閉。當所有的線程都處於活動狀態時,新任務都會處於等待狀態,直到有線程空閑出來。

只有核心線程並且不會被回收,能夠更加快速的響應外界的請求。

2. Executors.newCachedThreadPool()

    創建一個可緩存的線程池,如果當前線程池的長度超過了處理的需要時,它可以靈活的回收空閑的線程,當需要增加時,它可以靈活的添加新的線程,而不會對池的長度作任何限制

    線程數量不定的線程池,只有非核心線程,最大線程數為 Integer.MAX_VALUE。當線程池中的線程都處於活動狀態時,線程池會創建新的線程來處理新任務,否則利用空閑的線程來處理新任務。線程池中的空閑線程具有超時機制,為 60s。

    任務隊列相當於一個空集合,導致任何任務都會立即被執行,適合執行大量耗時較少的任務。當整個線程池都處於限制狀態時,線程池中的線程都會超時而被停止。

3. Executors.newScheledThreadPool()

    創建一個定長的線程池,而且支持定時的以及周期性的任務執行,類似於Timer。

    非核心線程數沒有限制,並且非核心線程閑置的時候立即回收,主要用於執行定時任務和具有固定周期的重復任務。

4. Executors.newSingleThreadExecutor()

    創建一個單線程化的executor,它只創建唯一的worker線程來執行任務

    只有一個核心線程,保證所有的任務都在一個線程中順序執行,意義在於不需要處理線程同步的問題。

    一般用於執行後台耗時任務,當任務執行完成會自動停止;同時由於它是一個服務,優先順序要遠遠高於線程,更不容易被系統殺死,因此比較適合執行一些高優先順序的後台任務。

使用步驟:創建IntentService的子類,重寫onHandleIntent方法,在onHandleIntent中執行耗時任務

    原理:在源碼實現上,IntentService封裝了HandlerThread和Handler。onHandleIntent方法結束後會調用IntentService的stopSelf(int startId)方法嘗試停止服務。

    IntentService的內部是通過消息的方式請求HandlerThread執行任務,HandlerThread內部又是一種使用Handler的Thread,這就意味著IntentService和Looper一樣是順序執行後台任務的

(HandlerThread:封裝了Handler + ThreadHandlerThread適合在有需要一個工作線程(非UI線程)+任務的等待隊列的形式,優點是不會有堵塞,減少了對性能的消耗,缺點是不能同時進行多個任務的處理,需要等待進行處理。處理效率低,可以當成一個輕量級的線程池來用)

『貳』 android 大量多線程怎麼優化

在程序開發的實踐當中,為了讓程序表現得更加流暢,我們肯定會需要使用到多線程來提升程序的並發執行性能。但是編寫多線程並發的代碼一直以來都是一個相對棘手的問題,所以想要獲得更佳的程序性能,我們非常有必要掌握多線程並發編程的基礎技能。
眾所周知,Android 程序的大多數代碼操作都必須執行在主線程,例如系統事件(例如設備屏幕發生旋轉),輸入事件(例如用戶點擊滑動等),程序回調服務,UI 繪制以及鬧鍾事件等等。那麼我們在上述事件或者方法中插入的代碼也將執行在主線程。

一旦我們在主線程裡面添加了操作復雜的代碼,這些代碼就很可能阻礙主線程去響應點擊/滑動事件,阻礙主線程的 UI 繪制等等。我們知道,為了讓屏幕的刷新幀率達到 60fps,我們需要確保 16ms 內完成單次刷新的操作。一旦我們在主線程裡面執行的任務過於繁重就可能導致接收到刷新信號的時候因為資源被佔用而無法完成這次刷新操作,這樣就會產生掉幀的現象,刷新幀率自然也就跟著下降了(一旦刷新幀率降到 20fps 左右,用戶就可以明顯感知到卡頓不流暢了)。

為了避免上面提到的掉幀問題,我們需要使用多線程的技術方案,把那些操作復雜的任務移動到其他線程當中執行,這樣就不容易阻塞主線程的操作,也就減小了出現掉幀的可能性。

那麼問題來了,為主線程減輕負的多線程方案有哪些呢?這些方案分別適合在什麼場景下使用?Android 系統為我們提供了若干組工具類來幫助解決這個問題。
AsyncTask: 為 UI 線程與工作線程之間進行快速的切換提供一種簡單便捷的機制。適用於當下立即需要啟動,但是非同步執行的生命周期短暫的使用場景。
HandlerThread: 為某些回調方法或者等待某些任務的執行設置一個專屬的線程,並提供線程任務的調度機制。
ThreadPool: 把任務分解成不同的單元,分發到各個不同的線程上,進行同時並發處理。
IntentService: 適合於執行由 UI 觸發的後台 Service 任務,並可以把後台任務執行的情況通過一定的機制反饋給 UI。
了解這些系統提供的多線程工具類分別適合在什麼場景下,可以幫助我們選擇合適的解決方案,避免出現不可預期的麻煩。雖然使用多線程可以提高程序的並發量,但是我們需要特別注意因為引入多線程而可能伴隨而來的內存問題。舉個例子,在 Activity 內部定義的一個 AsyncTask,它屬於一個內部類,該類本身和外面的 Activity 是有引用關系的,如果 Activity 要銷毀的時候,AsyncTask 還仍然在運行,這會導致 Activity 沒有辦法完全釋放,從而引發內存泄漏。所以說,多線程是提升程序性能的有效手段之一,但是使用多線程卻需要十分謹慎小心,如果不了解背後的執行機制以及使用的注意事項,很可能引起嚴重的問題。

『叄』 在Android下如何從網路中實現多線程下載文檔,比如開五個線程,文檔分成100份。一個線程負責其中的20份。

java中的多線程是一個道理,通過獲得的html頭信息,獲取文件大小,然後使用多線程分段下載
具體的可以到iteye搜索一下java多線程下載,記得以前在那裡見到過實例

『肆』 android後台多文件下載怎樣實現

可以創建一個服務,然後開啟多線程下載。不過不推薦多線程,建議使用單線程排隊下載。

『伍』 Android 多線程下載apk在一些機型上有一定概率出現apk安裝不了,看了一下apk的MD5改變了

你的這種接收方法不對。不能用len<0來判斷接收結束。因為流式傳輸中有粘包的現象,不能用len<0來判斷收包結束。

而應該在開始接收時,先接收一個長度,然後再根據長度去接收數據。

『陸』 android下載圖片和視頻到本地,求代碼,求案例

下面是android多線程下載例子截圖:

packagemm.shandong.com.testmultithreaddownload;
importandroid.app.ProgressDialog;
importandroid.content.Intent;
importandroid.net.Uri;
importandroid.os.Environment;
importandroid.os.Handler;
importandroid.os.Message;
importandroid.support.v7.app.AppCompatActivity;
importandroid.os.Bundle;
importandroid.text.TextUtils;
importandroid.view.View;
importandroid.widget.EditText;
importandroid.widget.Toast;
importjava.io.File;
importmm.shandong.com.testmultithreaddownload.thread.UpdateUIThread;
importmm.shandong.com.testmultithreaddownload.util.FileUtil;
{
ProgressDialogpb;
EditTexteditText;
Handlerhandler;
=null;
///文件路徑
privateStringurl=
"http://gdown..com/data/wisegame/3c00add7144d3915/kugouyinle.apk";
@Override
protectedvoidonCreate(BundlesavedInstanceState){
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_test_multi_thread_down_load);
editText=(EditText)findViewById(R.id.editText);
initHandler();
}
publicvoidinitHandler(){
handler=newHandler(){
@Override
publicvoidhandleMessage(Messagemsg){
switch(msg.what){
caseFileUtil.startDownloadMeg:
pb.setMax(mUpdateUIThread.getFileSize());//開始
break;
caseFileUtil.updateDownloadMeg:
if(!mUpdateUIThread.isCompleted())//下載進度消息
{
pb.setProgress(mUpdateUIThread.getDownloadSize());
pb.setMessage("下載速度:"+
mUpdateUIThread.getDownloadSpeed()+"k/秒"+
"下載百分比"+mUpdateUIThread.getDownloadPercent()+"%");
}else{
pb.setMessage("下載完成");
}
break;
caseFileUtil.endDownloadMeg:
Toast.makeText(.this,
"下載完成,馬上安裝",Toast.LENGTH_SHORT).show();
/*apk安裝界面跳轉*/
Stringfilename=FileUtil.getFileName(url);
Stringstr="/myfile/"+filename;
StringfileName=Environment.getExternalStorageDirectory()+str;
Intentintent=newIntent(Intent.ACTION_VIEW);
intent.setDataAndType(Uri.fromFile(newFile(fileName)),
"application/vnd.android.package-archive");
startActivity(intent);
break;
}
super.handleMessage(msg);
}
};
}
///開始下載軟體
publicvoidstartDownLoad(Viewview){
if(TextUtils.isEmpty(editText.getText().toString())){
Toast.makeText(this,"你輸入下載文件地址",Toast.LENGTH_SHORT).show();
return;
}else{
url=editText.getText().toString();
}
//啟動線程初始化下載參數
mUpdateUIThread=newUpdateUIThread(handler,url,
FileUtil.setMkdir(this)+File.separator,FileUtil.getFileName(url));
pb=newProgressDialog(this);
pb.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
pb.show();
mUpdateUIThread.start();
}
}

例子代碼太長,只能給你一部分,如果想看完整例子代碼,請去360手機助手下載安卓學習手冊,點擊裡面的源碼可以查看完成代碼,方面快速,裡面還有安卓的其它小例子,共108個。

『柒』 Android 開發.下載多張圖片保存到本地,大概9M,時間比較3~5分鍾。時間太長了,用戶會等太久,求解決方法

一張圖片的URL想要對應多張圖片基本實現不了,URL是唯一的存在,如果1個URL存在多個內容就出亂子了,除非這個URL不是JPG等結尾,而是HTML等頁面格式結尾,可以把多張圖片放在一個頁面當中。
可以有以下幾種方法:
1.將多張圖片處理成長條的1張圖片,保存時降低精度以減小圖片大小,下載時間可縮短並節約用戶流量。
2.將圖片打包成一個zip包-。-手機可能無法查看

其他方法想不到了。

『捌』 android編程如何實現邊下載邊播放

Android邊下載邊播放的實現應該需要用到多線程,一個線程下載,一個線程播放,具體可以找一個現有的音樂播放器源碼: http://www.mobizc.com/View.asp?ID=1253研究看看

『玖』 Android開發之路-多線程

多線程作為Android開發中相對而言較為高階的知識,其中用到相關的知識點是非常的多,所以在我們需要進行設計或者寫多線程的代碼就必須要進行相對謹慎的處理,這樣就由必要對其要有著比較系統化的認知

我們一般將Android應用分成為兩種:主線程和工作線程;主線程主要是用來進行初始化UI,而工作線程主要是進行耗時操作,例如讀取資料庫,網路連接等

Android系統是以進程為單位來對應用程序資源進行限制,這個問題的可以解釋為:一個進程最多能夠開幾個線程?最好能開幾個?但實則這個是沒有上限這一說,主要是因為資源的限制

Android中關於主線程的理解:Android的主線程是UI線程,在Android中,四大組件運行在主線程中,在主線程中做耗時操作會導致程序出現卡頓甚至出現ANR異常,一個.

在一個程序中,這些獨立運行的程序片斷叫作「線程」(Thread),利用它編程的概念就叫作「多線程處理」。多線程處理一個常見的例子就是用戶界面。

線程總的來就是進程的一個實體,是CPU進行分派和調度的基本單位,擁有著比進程更小且能夠獨立運行的基本單位,線程本身基本上是不擁有系統資源,僅擁有一點在運行過程中必須擁有的資源,但它可與同屬一個進程中的其他進程進行共享其所擁有的所有資源

線程狀態有些地方將之分為5中狀態,而且在Java Jdk中線程被其定義為6中狀態,我們可以對其進行類比

普遍定義的5中狀態:新建,就緒,運行,阻塞, 死亡

Java Jdk 定義狀態

線程阻塞是指在某一時刻的某一個線程在進行運行一段代碼的情況下,突然另一個線程也要進行運行,但在運行過程中,那個線程執行完全運行之前,另一個線程是不可能獲取到CPU的執行權,就會導致線路阻塞的出現

死鎖也稱之為抱死,意思就是說一個進程鎖定了另外一個進程所需要的頁或表是,但第二個進程同時又鎖定了第一個進程所需的一頁,這樣就會出現死鎖現象

簡要介紹實現線程的三種方式:繼承Thread,實現runnable,實現callable。這里有一點需要注意的是,實現callable是與線程池相關聯的而callable很重要的一個特性是其帶有返回值。當我們只需實現單線程時實現runnable更加利於線程程序的拓展

在線程開啟之前進行調用 thread.setDaemon(true); 將thread設定成當前線程中的守護線程 使用案例

線程讓步【yield方法】讓當前線程釋放CPU資源,讓其他線程搶占

這種具體某個對象鎖 wait & notify 方法與Condition 的 await以及signal方法類似; 全面這種方法的阻塞等待都可以是釋放鎖,而且在喚醒後,這種線程都是能夠獲取鎖資源的,而這個門栓就跟閥門類似

閱讀全文

與android多線程多任務下載相關的資料

熱點內容
如何用app覆蓋全部曲庫 瀏覽:602
變異布林源碼 瀏覽:684
表格加密設置列印區域 瀏覽:437
卡耐基pdf下載 瀏覽:922
現在最流行的單片機 瀏覽:88
機頂盒刷機源碼 瀏覽:985
編碼pdf下載 瀏覽:944
隔壁同學app怎麼 瀏覽:299
c語言宏命令 瀏覽:542
php卡死源碼 瀏覽:574
time庫中的clock函數python 瀏覽:989
cad視覺移動命令怎麼打開 瀏覽:821
安卓java調用python 瀏覽:395
java標准時間 瀏覽:137
華為伺服器湖北渠道商雲主機 瀏覽:30
韓式面部護理解壓視頻 瀏覽:301
pdf換成jpg圖片 瀏覽:897
dh加密演算法 瀏覽:107
安卓手機如何隱藏微信信息提示 瀏覽:632
nodejs解壓縮 瀏覽:262