摘要:多線程斷點下載原理獲取目標文件的大小在本地創(chuàng)建一個相同大小的文件并計算每個線程需要下載的起始位置及大小然后分配至每個線程獨立下載全部下載完畢則自動合并實現(xiàn)步驟查看并計算目標文件的大小文件總長度為設(shè)置目標文件在本地的映射開啟子線程并分配下載任
HTTP多線程斷點下載
實現(xiàn)步驟原理:獲取目標文件的大小,在本地創(chuàng)建一個相同大小的文件,并計算每個線程需要下載的起始位置及大小,然后分配至每個線程獨立下載,全部下載完畢則自動合并.
查看并計算目標文件的大小
URL url = new URL(mPath); HttpURLConnection connection = (HttpURLConnection) url.openConnection(); connection.setRequestMethod("GET"); int code = connection.getResponseCode(); if (code == 200) { int length = connection.getContentLength(); System.out.println("文件總長度為:" + length);
設(shè)置目標文件在本地的映射
RandomAccessFile raf = new RandomAccessFile( Environment.getExternalStorageDirectory().getAbsolutePath() +"/"+getDownlaodName(mPath), "rw"); raf.setLength(length);
開啟子線程并分配下載任務(wù)
int blokeSize = length / mTotalCount; System.out.println("每一塊大小為:" + blokeSize); runningThreadCount = mTotalCount; for (int threadid = 0; threadid < mTotalCount; threadid++) { int startPosition = threadid * blokeSize; int endPosition = (threadid + 1) * blokeSize - 1; //最后一個線程應(yīng)該下載至末尾 if (threadid == mTotalCount - 1) { endPosition = length - 1; } System.out.println("線程編號:" + threadid + "" + ",下載范圍:" + startPosition + "~~" + endPosition); //開啟下載子線程 new DownloadThread(threadid, startPosition, endPosition).start();
子線程中的具體邏輯
public void run() { System.out.println("線程"+threadid+"開始運行了"); try{ //讀存有歷史下載進度的文件,判斷是否已經(jīng)下載過 File finfo=new File(Environment.getExternalStorageDirectory().getAbsolutePath() +"/"+mTotalCount + getDownlaodName(mPath)+threadid+".txt"); if (finfo.exists()&&finfo.length()>0) { //獲取文件輸入流 FileInputStream fis=new FileInputStream(finfo); //讀取緩沖 BufferedReader br=new BufferedReader(new InputStreamReader(fis)); //得到文件內(nèi)容 String lasrposition=br.readLine(); //轉(zhuǎn)化為int值 int intlastposition=Integer.parseInt(lasrposition); lastLoadSize=intlastposition-startPosition; startPosition=intlastposition; fis.close(); } URL url=new URL(mPath); HttpURLConnection conn=(HttpURLConnection) url.openConnection(); conn.setRequestMethod("GET"); System.out.println("線程實際下載:"+threadid+",范圍:"+startPosition +"~~"+endPosition); //設(shè)置http請求頭部參數(shù) conn.setRequestProperty("Range", "bytes="+startPosition+"-"+endPosition); int code=conn.getResponseCode(); //206代表請求部分數(shù)據(jù)成功 if (code==206) { //拿到鏈接返回的輸入流 InputStream is=conn.getInputStream(); //指向要寫的文件(abc.exe) RandomAccessFile raf=new RandomAccessFile( Environment.getExternalStorageDirectory().getAbsolutePath() +"/"+getDownlaodName(mPath), "rw"); //指定文件開始寫的位置 raf.seek(startPosition); //下載緩沖區(qū),越大下載越快,對硬盤損耗越小,但是越容易丟失數(shù)據(jù) byte[] buffer=new byte[1024*1024]; int len=-1; int total=0;//當前線程本次下載數(shù)據(jù)總量 while ((len=is.read(buffer))!=-1) { raf.write(buffer,0,len); total+=len; //將每次更新的數(shù)據(jù)同步到底層硬盤 RandomAccessFile inforaf=new RandomAccessFile( Environment.getExternalStorageDirectory().getAbsolutePath() +"/"+mTotalCount +getDownlaodName(mPath)+threadid+".txt","rwd"); //保存當前線程下載到什么位置 inforaf.write(String.valueOf(startPosition+total).getBytes()); inforaf.close(); } is.close(); raf.close(); System.out.println("線程"+threadid+"下載完畢"); } }catch(Exception e){ e.printStackTrace(); }finally{ //同步代碼塊,保證同時間僅有一個線程執(zhí)行此區(qū)塊代碼 synchronized (MainActivity.class) { runningThreadCount--; if (runningThreadCount<=0) { System.out.println("多線程下載完畢"); for (int i = 0; i備注:如果不使用斷點下載,只需要將判斷和存儲歷史下載信息的邏輯刪除即可。
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://specialneedsforspecialkids.com/yun/64908.html
摘要:多線程下載原理及步驟在本地創(chuàng)建一個大小跟服務(wù)器文件相同大小的臨時文件。在這里在介紹一個有關(guān)多線程下載的中的相關(guān)類隨機文件訪問類只有才有搜尋方法,而這個方法也只適用于文件。利用這個類才能實現(xiàn)文件的多線程下載。 多線程下載在我們生活中非常常見,比如迅雷就是我們常用的多線程的下載工具,當然還有斷點續(xù)傳,斷點續(xù)傳我們在下一節(jié)來講,android手機端下載文件時也可以用多線程下載,我們這里是在j...
閱讀 1342·2021-09-24 10:26
閱讀 3655·2021-09-06 15:02
閱讀 605·2019-08-30 14:18
閱讀 577·2019-08-30 12:44
閱讀 3119·2019-08-30 10:48
閱讀 1936·2019-08-29 13:09
閱讀 1994·2019-08-29 11:30
閱讀 2279·2019-08-26 13:36