多線程

package com.jy.day15installapkmorethreaddownload;

import android.content.Context;
import android.util.Log;

import org.greenrobot.eventbus.EventBus;

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.net.URLConnection;

public class DownLoadMoreThread {
public static String TAG = "DownLoadMoreThread";
public static int thread_count = 5;
public static void httpDownLoadByMoreThreads(
final String apkUrl, final String savePath, final Context context){
ThreadManager.getInstance().execute(new Runnable() {
@Override
public void run() {
//計算每個線程要下載的模塊的開始位置和結(jié)束位置
try {
URL url= new URL(apkUrl);
HttpURLConnection urlConnection = (HttpURLConnection) url.openConnection();
int len = urlConnection.getContentLength();
EventBus.getDefault().post(new MsgE(0,len));//把文件的大小設(shè)置給進度條,保存一直,后面通過下載的數(shù)據(jù)的改變進度
////2.分配任務(wù),5個線程,
//假設(shè) 20個數(shù)據(jù):0-19
//線程0:0-3,線程1:4-7,線程2:8-11 ,...
int blockSize = len/thread_count;//得到每一個線程要下載的大小 4
//每次for循環(huán)計算出本次線程下載的數(shù)據(jù)的開始和結(jié)束位置
for (int i = 0; i < thread_count; i++) {
int start = iblockSize;//開始的位置
int end = (i+1)
blockSize-1;//結(jié)束的位置
if(i == thread_count-1){//如果當前是最后一個線程赶袄,則下載剩下的所有數(shù)據(jù)
end = len-1;
}
//啟動一個線程進行下載贸宏,沒有斷點
// downThread(i,start,end,apkUrl,savePath,len);
//帶斷點續(xù)傳的
downThreadCut(i,start,end,apkUrl,savePath,context,len);
}
} catch (Exception e) {
e.printStackTrace();
}
}
});
}

public static void downThread(
        final int i, final int start, final int end, final String apkUrl, final String savePath, final int max) {
        ThreadManager.getInstance().execute(new Runnable() {
        @Override
        public void run() {
            //進行下載
            try {
                URL url= new URL(apkUrl);
                HttpURLConnection conn = (HttpURLConnection) url.openConnection();
                ///設(shè)置請求部分資源   Range表示隨機位置   重點1
                conn.setRequestProperty("Range","bytes="+start+"-"+end); //設(shè)置當前線程從start開始  到 end結(jié)束
                int responseCode = conn.getResponseCode();
                //HttpURLConnection.HTTP_PARTIAL 是 206煤辨,表示允許請求部分數(shù)據(jù)
                if(responseCode == HttpURLConnection.HTTP_PARTIAL){
                    InputStream inputStream = conn.getInputStream();//得到本線程應(yīng)該讀取的部分數(shù)據(jù)
                    RandomAccessFile rf = new RandomAccessFile(savePath, "rw");//創(chuàng)建可以讀寫的隨機流  rw表示可讀可寫
                    rf.seek(start);//把隨機流偏移到 應(yīng)該開始的位置

                    byte[] bytes = new byte[2048];
                    int len = 0;
                    int count = 0;
                    int totalCount = end-start+1;//計算出本線程應(yīng)該下載的大小
                    while((len = inputStream.read(bytes)) != -1){
                        rf.write(bytes,0,len);
                        count += len;
                        Log.d("MainActivity", "線程:"+i+",totalCount: "+totalCount+
                                ",百分比:"+(float)count/totalCount+"厂镇,下載大小:"+count);
                        EventBus.getDefault().post(new MsgE(len,max));//把當前下載的長度發(fā)出去叁丧,Activity接收,顯示在進度條上
                    }
                    Log.i("MainActivity", "run: 線程"+i+"下載完畢");
                    inputStream.close();
                    rf.close();
                }

            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    });
}


public static void downThreadCut(
        final int i, final int start, final int end, final String apkUrl, final String savePath, final Context context, final int max) {
    ThreadManager.getInstance().execute(new Runnable() {
        @Override
        public void run() {
            //進行下載
            try {
                URL url= new URL(apkUrl);
                HttpURLConnection conn = (HttpURLConnection) url.openConnection();
                //得到SharedPreferences保存的本線程上傳下載的位置
                int currentPosition = start;  //currentPosition當前下載的開始位置
                int  n = (int) SharedPreferencesUtils.getParam(context, "線程" + i, 0);
                if(n == 0){
                    Log.i("MainActivity", "run: 第一次下載");
                }else {//有值岳瞭,說明上次下載沒有完成歹袁,記錄了下載到的位置,從此下載
                    currentPosition = n;
                    Log.i("MainActivity", "run:線程"+i+" 接著上次下載,開始位置是:"+currentPosition);
                }
                ///設(shè)置請求部分資源   Range表示隨機位置
                conn.setRequestProperty("Range","bytes="+currentPosition+"-"+end); //設(shè)置當前線程從start開始  到 end結(jié)束
                int responseCode = conn.getResponseCode();
                //HttpURLConnection.HTTP_PARTIAL 是 206寝优,表示允許請求部分數(shù)據(jù)
                if(responseCode == HttpURLConnection.HTTP_PARTIAL){
                    InputStream inputStream = conn.getInputStream();//得到本線程應(yīng)該讀取的部分數(shù)據(jù)
                    RandomAccessFile rf = new RandomAccessFile(savePath, "rw");//創(chuàng)建可以讀寫的隨機流
                    rf.seek(currentPosition);//把隨機流偏移到 應(yīng)該開始的位置条舔,上次下載寫入的位置(下載了一部分)

                    byte[] bytes = new byte[2048];
                    int len = 0;
                    int count = currentPosition-start;//計算出已經(jīng)下載的大小
                    EventBus.getDefault().post(new MsgE(count,max));//把得到的舊進度,設(shè)置到進度條中

// myCallBack.setProgress2(count);//把已經(jīng)下載的數(shù)據(jù)量給進度條
int totalCount = end-start+1;//計算出本線程應(yīng)該下載的大小
while((len = inputStream.read(bytes)) != -1){
rf.write(bytes,0,len);
count += len;//記錄下載的大小
currentPosition += len;//把下載位置向前移動len乏矾,以為又下載了len長度的數(shù)據(jù)
Log.d("MainActivity", "線程:"+i+",totalCount: "+totalCount+
",百分比:"+(float)count/totalCount+"孟抗,下載大星ㄑ睢:"+count);
// myCallBack.setProgress2(len);//把新下載的數(shù)據(jù)量給進度條
//通過SharedPreferencesUtils記錄當前下載到的位置,供105行獲取使用凄硼,供下次下載使用
EventBus.getDefault().post(new MsgE(len,max));//把得到的新進度铅协,設(shè)置到進度條中
SharedPreferencesUtils.setParam(context,"線程"+i,currentPosition);
}
//本線程下載完畢,重新設(shè)置為0.下回重新下載
SharedPreferencesUtils.setParam(context,"線程"+i,0);
Log.i("MainActivity", "run: 線程"+i+"下載完畢");
inputStream.close();
rf.close();
}

            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    });
}

}

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末摊沉,一起剝皮案震驚了整個濱河市狐史,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌说墨,老刑警劉巖骏全,帶你破解...
    沈念sama閱讀 221,548評論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異尼斧,居然都是意外死亡姜贡,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,497評論 3 399
  • 文/潘曉璐 我一進店門棺棵,熙熙樓的掌柜王于貴愁眉苦臉地迎上來楼咳,“玉大人,你說我怎么就攤上這事烛恤∧噶” “怎么了?”我有些...
    開封第一講書人閱讀 167,990評論 0 360
  • 文/不壞的土叔 我叫張陵缚柏,是天一觀的道長糙申。 經(jīng)常有香客問我,道長船惨,這世上最難降的妖魔是什么柜裸? 我笑而不...
    開封第一講書人閱讀 59,618評論 1 296
  • 正文 為了忘掉前任,我火速辦了婚禮粱锐,結(jié)果婚禮上疙挺,老公的妹妹穿的比我還像新娘。我一直安慰自己怜浅,他們只是感情好铐然,可當我...
    茶點故事閱讀 68,618評論 6 397
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著恶座,像睡著了一般搀暑。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上跨琳,一...
    開封第一講書人閱讀 52,246評論 1 308
  • 那天自点,我揣著相機與錄音,去河邊找鬼脉让。 笑死桂敛,一個胖子當著我的面吹牛功炮,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播术唬,決...
    沈念sama閱讀 40,819評論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼薪伏,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了粗仓?” 一聲冷哼從身側(cè)響起嫁怀,我...
    開封第一講書人閱讀 39,725評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎借浊,沒想到半個月后塘淑,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 46,268評論 1 320
  • 正文 獨居荒郊野嶺守林人離奇死亡巴碗,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 38,356評論 3 340
  • 正文 我和宋清朗相戀三年朴爬,在試婚紗的時候發(fā)現(xiàn)自己被綠了即寒。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片橡淆。...
    茶點故事閱讀 40,488評論 1 352
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖母赵,靈堂內(nèi)的尸體忽然破棺而出逸爵,到底是詐尸還是另有隱情,我是刑警寧澤凹嘲,帶...
    沈念sama閱讀 36,181評論 5 350
  • 正文 年R本政府宣布师倔,位于F島的核電站,受9級特大地震影響周蹭,放射性物質(zhì)發(fā)生泄漏趋艘。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,862評論 3 333
  • 文/蒙蒙 一凶朗、第九天 我趴在偏房一處隱蔽的房頂上張望瓷胧。 院中可真熱鬧,春花似錦棚愤、人聲如沸搓萧。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,331評論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽瘸洛。三九已至,卻和暖如春次和,著一層夾襖步出監(jiān)牢的瞬間反肋,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,445評論 1 272
  • 我被黑心中介騙來泰國打工踏施, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留囚玫,地道東北人喧锦。 一個月前我還...
    沈念sama閱讀 48,897評論 3 376
  • 正文 我出身青樓,卻偏偏與公主長得像抓督,于是被迫代替她去往敵國和親燃少。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 45,500評論 2 359

推薦閱讀更多精彩內(nèi)容

  • Java多線程學習 [-] 一擴展javalangThread類 二實現(xiàn)javalangRunnable接口 三T...
    影馳閱讀 2,964評論 1 18
  • 本文主要講了java中多線程的使用方法铃在、線程同步阵具、線程數(shù)據(jù)傳遞、線程狀態(tài)及相應(yīng)的一些線程函數(shù)用法定铜、概述等阳液。 首先講...
    李欣陽閱讀 2,458評論 1 15
  • Android多線程斷點續(xù)傳下載 原理 其實斷點續(xù)傳的原理很簡單,從字面上理解揣炕,所謂斷點續(xù)傳就是從停止的地方重新下...
    壓抑的內(nèi)心閱讀 671評論 0 0
  • 點上一爐香帘皿,沏上一杯茶,開始描述我今天的故事畸陡。 在我的桌面上鹰溜,筆記本電腦鍵盤上放著一條紅底碎花的絲巾,...
    青玉案子衿閱讀 524評論 0 7
  • 虛幻里的自戀 早晨院里溜個彎 也能把小短腿變成超長腿的麻豆 真是沒有PS也擋不住的節(jié)奏岸」А曹动! 人家朝陽不就是捎帶把你...
    頌奇2018閱讀 327評論 3 2