国产片侵犯亲女视频播放_亚洲精品二区_在线免费国产视频_欧美精品一区二区三区在线_少妇久久久_在线观看av不卡

服務(wù)器之家:專注于服務(wù)器技術(shù)及軟件下載分享
分類導(dǎo)航

PHP教程|ASP.NET教程|Java教程|ASP教程|編程技術(shù)|正則表達(dá)式|C/C++|IOS|C#|Swift|Android|VB|R語言|JavaScript|易語言|vb.net|

服務(wù)器之家 - 編程語言 - Android - PC版與Android手機版帶斷點續(xù)傳的多線程下載

PC版與Android手機版帶斷點續(xù)傳的多線程下載

2021-04-02 16:48Android開發(fā)網(wǎng) Android

這篇文章主要介紹了PC版與Android手機版帶斷點續(xù)傳的多線程下載的相關(guān)資料,需要的朋友可以參考下

一、多線程下載

        多線程下載就是搶占服務(wù)器資源

        原理:服務(wù)器CPU 分配給每條線程的時間片相同,服務(wù)器帶寬平均分配給每條線程,所以客戶端開啟的線程越多,就能搶占到更多的服務(wù)器資源。

      1、設(shè)置開啟線程數(shù),發(fā)送http請求到下載地址,獲取下載文件的總長度
          然后創(chuàng)建一個長度一致的臨時文件,避免下載到一半存儲空間不夠了,并計算每個線程下載多少數(shù)據(jù)      
       2、計算每個線程下載數(shù)據(jù)的開始和結(jié)束位置
          再次發(fā)送請求,用 Range 頭請求開始位置和結(jié)束位置的數(shù)據(jù)
       3、將下載到的數(shù)據(jù),存放至臨時文件中
       4、帶斷點續(xù)傳的多線程下載

          定義一個int變量,記錄每條線程下載的數(shù)據(jù)總長度,然后加上該線程的下載開始位置,得到的結(jié)果就是下次下載時,該線程的開始位置,把得到的結(jié)果存入緩存文件,當(dāng)文件下載完成,刪除臨時進(jìn)度文件。

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
public class MultiDownload {
   static int ThreadCount = ;
   static int finishedThread = ;
   //確定下載地址
   static String filename = "EditPlus.exe";
   static String path = "http://...:/"+filename;
   public static void main(String[] args) {
     //、發(fā)送get請求,去獲得下載文件的長度
    try {
      URL url = new URL(path);
      HttpURLConnection conn = (HttpURLConnection) url.openConnection();
      conn.setRequestMethod("GET");
      conn.setConnectTimeout();
      conn.setReadTimeout();
      if (conn.getResponseCode()==) {
        //如果請求成功,拿到所請求資源文件的長度
        int length = conn.getContentLength();
        //、生成一個與原文件同樣的大小的臨時文件,以免下載一半存儲空間不夠了
        File file = new File(filename);//演示,所以將保存的文件目錄放在工程的同目錄
        //使用RandomAccessFile 生成臨時文件,可以用指針定位文件的任意位置,
        //而且能夠?qū)崟r寫到硬件底層設(shè)備,略過緩存,這對下載文件是突然斷電等意外是有好處的
        RandomAccessFile raf = new RandomAccessFile(file, "rwd");//rwd, 實時寫到底層設(shè)備
        //設(shè)置臨時文件的大小
        raf.setLength(length);
        raf.close();
        //、計算出每個線程應(yīng)該下載多少個字節(jié)
        int size = length/ThreadCount;//如果有余數(shù),負(fù)責(zé)最后一部分的線程負(fù)責(zé)下砸
        //開啟多線程
        for (int threadId = ; threadId < ThreadCount; threadId++) {
          //計算每個線程下載的開始位置和結(jié)束位置
          int startIndex = threadId*size; // 開始 = 線程id * size
          int endIndex = (threadId+)*size - ; //結(jié)束 = (線程id + )*size -
          //如果是最后一個線程,那么結(jié)束位置寫死為文件結(jié)束位置
          if (threadId == ThreadCount - ) {
            endIndex = length - ;
          }
          //System.out.println("線程"+threadId+"的下載區(qū)間是: "+startIndex+"----"+endIndex);
          new DownloadThread(startIndex,endIndex,threadId).start();
        }
      }
    } catch (MalformedURLException e) {
      e.printStackTrace();
    } catch (IOException e) {
      e.printStackTrace();
    }
  }
}
class DownloadThread extends Thread{
  private int startIndex;
  private int endIndex;
  private int threadId;
  public DownloadThread(int startIndex, int endIndex, int threadId) {
    super();
    this.startIndex = startIndex;
    this.endIndex = endIndex;
    this.threadId = threadId;
  }
   public void run() {
     //每個線程再次發(fā)送http請求,下載自己對應(yīng)的那部分?jǐn)?shù)據(jù)
    try {
      File progressFile = new File(threadId+".txt");
      //判斷進(jìn)度文件是否存在,如果存在,則接著斷點繼續(xù)下載,如果不存在,則從頭下載
      if (progressFile.exists()) {
        FileInputStream fis = new FileInputStream(progressFile);
        BufferedReader br = new BufferedReader(new InputStreamReader(fis));
        //從進(jìn)度文件中度取出上一次下載的總進(jìn)度,然后與原本的開始進(jìn)度相加,得到新的開始進(jìn)度
        startIndex += Integer.parseInt(br.readLine());
        fis.close();
      }
      System.out.println("線程"+threadId+"的下載區(qū)間是:"+startIndex+"----"+endIndex);
      //、每個線程發(fā)送http請求自己的數(shù)據(jù)
      URL url = new URL(MultiDownload.path);
      HttpURLConnection conn = (HttpURLConnection) url.openConnection();
      conn.setRequestMethod("GET");
      conn.setConnectTimeout();
      conn.setReadTimeout();
      //設(shè)置本次http請求所請求的數(shù)據(jù)的區(qū)間
      conn.setRequestProperty("Range", "bytes="+startIndex+"-"+endIndex);
      //請求部分?jǐn)?shù)據(jù),響應(yīng)碼是
      if (conn.getResponseCode()==) {
        //此時,流里只有ThreadCount分之一的原文件數(shù)據(jù)
        InputStream is = conn.getInputStream();
        byte[] b = new byte[];
        int len = ;
        int total = ;//total 用于保存斷點續(xù)傳的斷點
        //拿到臨時文件的輸出流
        File file = new File(MultiDownload.filename);
        RandomAccessFile raf = new RandomAccessFile(file, "rwd");
        //把文件的寫入位置移動至 startIndex
        raf.seek(startIndex);
        while ((len = is.read(b))!=-) {
          //每次讀取流里數(shù)據(jù)之后,同步把數(shù)據(jù)寫入臨時文件
          raf.write(b, , len);
          total += len;
          //System.out.println("線程" + threadId + "下載了" + total);
          //生成一個一個專門用來記錄下載進(jìn)度的臨時文件
          RandomAccessFile progressRaf = new RandomAccessFile(progressFile, "rwd");
          progressRaf.write((total+"").getBytes());
          progressRaf.close();
        }
        System.out.println("線程"+threadId+"下載完了---------------------");
        raf.close();
        //當(dāng)所有的線程下載完之后,將進(jìn)度文件刪除
        MultiDownload.finishedThread++;
        synchronized (MultiDownload.path) {//所有線程使用同一個鎖
          if (MultiDownload.finishedThread==MultiDownload.ThreadCount) {
            for (int i = ; i < MultiDownload.ThreadCount; i++) {
              File f = new File(i+".txt");
              f.delete();
            }
            MultiDownload.finishedThread=;
          }
        }
      
    } catch (Exception e) {
      e.printStackTrace();
    }
  }
}

二、Android手機版帶斷點續(xù)傳的多線程下載

     Android手機版的帶斷點續(xù)傳的多線程下載邏輯與PC版的幾乎一樣,只不過在Android手機中耗時操作不能放在主線程,網(wǎng)絡(luò)下載屬于耗時操作,所以多線程下載要在Android中開啟一個子線程執(zhí)行。并使用消息隊列機制刷新文本進(jìn)度條。

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
public class MainActivity extends Activity {
  static int ThreadCount = ;
  static int FinishedThread = ;
  int currentProgess;
  static String Filename = "QQPlayer.exe";
  static String Path = "http://...:/"+Filename;
  static MainActivity ma;
  static ProgressBar pb;
  static TextView tv;
  static Handler handler = new Handler(){
    public void handleMessage(android.os.Message msg){
      tv.setText((long)pb.getProgress()* /pb.getMax() +"%");
    };
  };
  protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    ma = this;
    pb = (ProgressBar) findViewById(R.id.pb);
    tv = (TextView) findViewById(R.id.tv);
  }
  public void download(View v){
    Thread t = new Thread(){
      public void run() {
        //發(fā)送http請求獲取文件的長度,創(chuàng)建臨時文件
        try {
          URL url= new URL(Path);
          HttpURLConnection conn = (HttpURLConnection) url.openConnection();
          conn.setRequestMethod("GET");
          conn.setConnectTimeout();
          conn.setReadTimeout();
          if (conn.getResponseCode()==) {
            int length = conn.getContentLength();
            //設(shè)置進(jìn)度條的最大值就是原文件的總長度
            pb.setMax(length);
            //生成一個與原文件相同大小的臨時文件
            File file = new File(Environment.getExternalStorageDirectory(),Filename);
            RandomAccessFile raf = new RandomAccessFile(file, "rwd");
            raf.setLength(length);
            raf.close();
            //計算每個線程需要下載的數(shù)據(jù)大小
            int size = length/ThreadCount;
            //開啟多線程
            for (int threadId = ; threadId < ThreadCount; threadId++) {
              int startIndex = threadId*size;
              int endIndex = (threadId + )*size - ;
              if (threadId==ThreadCount - ) {
                endIndex = length - ;
              }
              new DownloadThread(startIndex, endIndex, threadId).start();
            }
          }
        } catch (Exception e) {
          e.printStackTrace();
        }
      }
    };
    t.start();
  }
  class DownloadThread extends Thread{
    private int startIndex;
    private int endIndex;
    private int threadId;
    public DownloadThread(int startIndex, int endIndex, int threadId) {
      super();
      this.startIndex = startIndex;
      this.endIndex = endIndex;
      this.threadId = threadId;
    }
    public void run() {
      // 每個線程發(fā)送http請求自己的數(shù)據(jù)
      try{
        //先判斷是不是斷點續(xù)傳
        File progessFile = new File(Environment.getExternalStorageDirectory(),threadId+".txt");
        if (progessFile.exists()) {
          FileReader fr = new FileReader(progessFile);
          BufferedReader br = new BufferedReader(fr);
          int lastProgess = Integer.parseInt(br.readLine());
          startIndex += lastProgess;
          //把上次下載的進(jìn)度顯示至進(jìn)度條
          currentProgess +=lastProgess;
          pb.setProgress(currentProgess);
          //發(fā)消息,讓主線程刷新文本進(jìn)度
          handler.sendEmptyMessage();
          br.close();
          fr.close();
        }
        URL url = new URL(Path);
        HttpURLConnection conn = (HttpURLConnection) url.openConnection();
        conn.setRequestMethod("GET");
        conn.setConnectTimeout();
        conn.setReadTimeout();
        conn.setRequestProperty("Range", "bytes="+startIndex+"-"+endIndex);
        if (conn.getResponseCode()==) {
          InputStream is = conn.getInputStream();
          byte[] buffer = new byte[];
          int len = ;
          int total = ;
          File file = new File(Environment.getExternalStorageDirectory(),Filename);
          RandomAccessFile raf = new RandomAccessFile(file, "rwd");
          raf.seek(startIndex);
          while ((len = is.read(buffer))!= -) {
            raf.write(buffer, , len);
            total += len;
            //每次讀取流里數(shù)據(jù)之后,把本次讀取的數(shù)據(jù)的長度顯示至進(jìn)度條
            currentProgess += len;
            pb.setProgress(currentProgess);
            //發(fā)消息,讓主線程刷新文本進(jìn)度
            handler.sendEmptyMessage();
            //生成臨時文件保存下載進(jìn)度,用于斷點續(xù)傳,在所有線程現(xiàn)在完畢后刪除臨時文件
            RandomAccessFile progressRaf = new RandomAccessFile(progessFile, "rwd");
            progressRaf.write((total+"").getBytes());
            progressRaf.close();
          }
          raf.close();
          System.out.println("線程"+threadId+"下載完了");
          //當(dāng)所有線程都下在完了之后,刪除臨時進(jìn)度文件
          FinishedThread++;
          synchronized (Path) {
            if (FinishedThread==ThreadCount) {
              for (int i = ; i < ThreadCount; i++) {
                File f = new File(Environment.getExternalStorageDirectory(),i+".txt");
                f.delete();
              }
              FinishedThread=;
            }
          }
        }
      } catch (Exception e) {
        e.printStackTrace();
      }
    }
  }
}

以上內(nèi)容是小編跟大家分享的PC版與Android手機版帶斷點續(xù)傳的多線程下載,希望大家喜歡。

延伸 · 閱讀

精彩推薦
主站蜘蛛池模板: 一区二区三区视频 | 亚洲欧美在线一区 | 国产一级二级毛片 | 亚洲免费视频一区 | 亚洲视频在线免费观看 | 日韩超碰在线观看 | 黄色美女免费 | 久久久91精品国产一区二区三区 | 精品国产91乱码一区二区三区 | 色综合天天综合网国产成人网 | 久久亚洲国产精品 | 欧美三级影院 | 欧美成人激情视频 | 精品成人免费一区二区在线播放 | 久久久久这里只有精品 | 久久久久久人 | 精品自拍视频在线观看 | 免费观看www7722午夜电影 | 欧美精品一二三区 | 国产成人在线电影 | 欧美激情精品久久久久久 | 欧美综合第一页 | 成年女人免费v片 | 国产一级毛片电影 | 亚洲一区亚洲二区 | 在线观看成人 | 亚洲久久久久久 | 欧美中文字幕一区二区 | 亚洲视频第一页 | 午夜免费av | 久久久精品| 欧美激情在线观看 | 一本一本久久a久久精品综合妖精 | 国产aⅴ | 久久久久久网站 | 亚洲一区免费在线观看 | 四季久久免费一区二区三区四区 | 欧美a级片在线观看 | 国产一区二区h | 日韩一区二区在线免费 | 国产一区|