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

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 运维知识 > Android >内容正文

Android

Android模拟多线程下载

發布時間:2025/3/21 Android 35 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Android模拟多线程下载 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

本DEMO采用Executor框架來實現多線程的下載。
Executor原理:任務拆分為一些列的小任務,即Runnable,然后在提交給一個Executor執行,Executor.execute(Runnalbe) 。Executor在執行時使用內部的線程池完成操作。
本博文演示的從服務端多線程下載圖片主要是通過HTTP請求頭的Range,在線程池中初始化線程數,然后根據算法去計算,每個線程去下載指定Range范圍的資源,每個線程現在完成后發送Message消息給主線程的handler ,當所有的線程都下載完成后,handler主動更新主線程UI。
詳細代碼請移步本人GITHUB

客戶端核心代碼

package com.turing.base.http.downHttp;import android.os.Environment; import android.os.Handler; import android.os.Message;import com.apkfuns.logutils.LogUtils;import java.io.File; import java.io.IOException; import java.io.InputStream; import java.io.RandomAccessFile; import java.net.HttpURLConnection; import java.net.MalformedURLException; import java.net.URL; import java.util.concurrent.Executor; import java.util.concurrent.Executors;/*** MyApp** @author Mr.Yang on 2015-11-18 18:58.* @version 1.0* 多線程下載的實現過程:* 1、首先得到下載文件的長度,然后設置本地文件* 的長度。* HttpURLConnection.getContentLength();* RandomAccessFile file = new RandomAccessFile("QQWubiSetup.exe","rwd");* file.setLength(filesize);//設置本地文件的長度* 2、根據文件長度和線程數計算每條線程下載的數據長度和下載位置。* 如:文件的長度為6M,線程數為3,那么,每條線程下載的數據長度為2M,每條線程開始下載的位置如上圖所示。* 3、使用Http的Range頭字段指定每條線程從文件的什么位置開始下載,下載到什么位置為止,* 如:指定從文件的2M位置開始下載,下載到位置(4M-1byte)為止,代碼如下:* con.setRequestProperty("Range", "bytes=" + 開始位置+ "-" + "結束位置");* HttpURLConnection.setRequestProperty("Range","bytes=2097152-4194303");* 4、保存文件,使用RandomAccessFile類指定每條線程從本地文件的什么位置開始寫入數據。* RandomAccessFile threadfile = newRandomAccessFile("QQWubiSetup.exe ","rwd");* threadfile.seek(2097152);//從文件的什么位置開始寫入數據*/ public class DownLoad {// 創建線程池,指定大小private Executor threadPool = Executors.newFixedThreadPool(3);public void downLoadFile(String url, Handler handler) {try {// 根據URL實例化URLURL httpUrl = new URL(url);// 打開連接HttpURLConnection conn = (HttpURLConnection) httpUrl.openConnection();// 設置屬性conn.setRequestMethod("GET");conn.setReadTimeout(1000 * 5);// 因為要通過線程池-多線程下載文件,所以應該先獲取總長度,然后分配每個線程的下載大小int count = conn.getContentLength();// 假設通過三個線程下載,計算每個線程的下載大小int block = count / 3;// 遍歷 計算出每個線程獲取內容的起始位置// 獲取文件名稱String fileName = getFileName(url);LogUtils.d("fileName:" + fileName);// 指定文件的下載地址,加載到sd卡中File parent = Environment.getExternalStorageDirectory();File downFile = new File(parent, fileName);for (int i = 0; i < 3; i++) {// 算法解釋 假設文件的大小為11個字節,我們通過線程池開啟3個線程,這樣還剩余2個字節,在最后的線程里處理// 第一個線程 從0開始獲取到2// 第二個線程 從3開始獲取到5// 第三個線程 從6到10long start = i * block;long end = (i + 1) * block - 1;if (i == 2) {end = count;}LogUtils.d("start:" + start + ",end" + end);// 實例化Runnable對象LogUtils.d("getAbsolutePath:" + downFile.getAbsolutePath());DownLoadRunnnable downLoadRunnnable = new DownLoadRunnnable(url, downFile.getAbsolutePath(), start, end, handler);// 提交到線程池threadPool.execute(downLoadRunnnable);LogUtils.d("execute成功");}} catch (MalformedURLException e) {e.printStackTrace();} catch (IOException e) {e.printStackTrace();}}/*** 根據URL的后綴 獲取要獲取的圖片文件名稱* http://localhost:8080/HttpService/girl.jpg*/public String getFileName(String url) {// 獲取最后一個/ 截取文件名稱return url.substring(url.lastIndexOf("/") + 1);}/*** DownLoadRunnnable對象*/static class DownLoadRunnnable implements Runnable {private String url;private String fileName;private long start;private long end;private Handler handler;// 構造函數public DownLoadRunnnable(String url, String fileName, long start, long end, Handler handler) {this.url = url;this.fileName = fileName;this.start = start;this.end = end;this.handler = handler;}@Overridepublic void run() {try {URL downLoadURL = new URL(url);HttpURLConnection conn = (HttpURLConnection) downLoadURL.openConnection();conn.setReadTimeout(1000 * 5);conn.setRequestMethod("GET");//使用Http的Range頭字段指定每條線程從文件的什么位置開始下載,下載到什么位置為止,這里指定從開始到結束conn.setRequestProperty("Range", "bytes=" + start + "-" + end);// 保存文件/**public RandomAccessFile(File file, String mode) throws FileNotFoundException創建從中讀取和向其中寫入(可選)的隨機訪問文件流,該文件由 File 參數指定。將創建一個新的 FileDescriptor 對象來表示此文件的連接。mode 參數指定用以打開文件的訪問模式。允許的值及其含意為:值 含意"r" 以只讀方式打開。調用結果對象的任何 write 方法都將導致拋出 IOException。"rw" 打開以便讀取和寫入。如果該文件尚不存在,則嘗試創建該文件。"rws" 打開以便讀取和寫入,對于 "rw",還要求對文件的內容或元數據的每個更新都同步寫入到底層存儲設備。"rwd" 打開以便讀取和寫入,對于 "rw",還要求對文件內容的每個更新都同步寫入到底層存儲設備。**/RandomAccessFile accessFile = new RandomAccessFile(new File(fileName), "rwd");//從文件的什么位置開始寫入數據accessFile.seek(start);// 獲取輸入流InputStream ins = conn.getInputStream();// 設置緩沖區域byte[] b = new byte[1024 * 4];int len;// 循環讀取寫入accessFilewhile ((len = ins.read(b)) != -1) {accessFile.write(b, 0, len);}LogUtils.d("write 成功");// 關閉流if (accessFile != null) {accessFile.close();}if (ins != null) {ins.close();}// 發送消息通知主線程完成Message message = new Message();message.what = 1 ;handler.sendMessage(message);LogUtils.d("message發送成功");} catch (MalformedURLException e) {e.printStackTrace();} catch (IOException e) {e.printStackTrace();}}}}

總結

以上是生活随笔為你收集整理的Android模拟多线程下载的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。