一区二区三区在线-一区二区三区亚洲视频-一区二区三区亚洲-一区二区三区午夜-一区二区三区四区在线视频-一区二区三区四区在线免费观看

服務器之家:專注于服務器技術及軟件下載分享
分類導航

PHP教程|ASP.NET教程|JAVA教程|ASP教程|

服務器之家 - 編程語言 - JAVA教程 - java多線程下載實例詳解

java多線程下載實例詳解

2020-03-13 13:37sgx425021234 JAVA教程

這篇文章主要介紹了java多線程下載,結合實例形式詳細分析了Java多線程文件傳輸的原理與多線程下載的相關實現技巧,需要的朋友可以參考下

本文實例講述了java多線程下載。分享給大家供大家參考,具體如下:

使用多線程下載文件可以更快完成文件的下載,多線程下載文件之所以快,是因為其搶占的服務器資源多。如:假設服務器同時最多服務100個用戶,在服務器中一條線程對應一個用戶,100條線程在計算機中并非并發執行,而是由CPU劃分時間片輪流執行,如果A應用使用了99條線程下載文件,那么相當于占用了99個用戶的資源,假設一秒內CPU分配給每條線程的平均執行時間是10ms,A應用在服務器中一秒內就得到了990ms的執行時間,而其他應用在一秒內只有10ms的執行時間。就如同一個水龍頭,每秒出水量相等的情況下,放990毫秒的水肯定比放10毫秒的水要多。

多線程下載的實現過程:

1.首先得到下載文件的長度,然后設置本地文件的長度。

?
1
2
3
HttpURLConnection.getContentLength();
RandomAccessFile file = new RandomAccessFile("youdao.exe","rw");
file.setLength(filesize);//設置本地文件的長度

2.根據文件長度和線程數計算每條線程下載的數據長度和下載位置。如:文件的長度為6M,線程數為3,那么,每條線程下載的數據長度為2M,每條線程開始下載的位置如下圖所示。

java多線程下載實例詳解

3.使用Http的Range頭字段指定每條線程從文件的什么位置開始下載,如:指定從文件的2M位置開始下載文件,代碼如下:

復制代碼 代碼如下:
HttpURLConnection.setRequestProperty("Range", "bytes=2097152-");

4.保存文件,使用RandomAccessFile類指定每條線程從本地文件的什么位置開始寫入數據

 

?
1
2
RandomAccessFile threadfile = new RandomAccessFile("<span style="font-family: Arial, Helvetica, sans-serif;">youdao.exe</span><span style="font-family: Arial, Helvetica, sans-serif;"> ","rw");</span>
threadfile.seek(2097152);//從文件的什么位置開始寫入數據

下面是通過具體實現類:

在寫實現類之前我們首先要將要下載的文件放在服務器上并部署:

我是放在了這里 D:\Tomcat\apache-tomcat-7.0.37\webapps\doudou目錄下,并啟動D:\Tomcat\apache-tomcat-7.0.37\bin下的startup.bat

1.DownLoadTest.java

?
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
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
package www.csdn.net.down;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.RandomAccessFile;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
public class DownLoadTest {
 public File file;
 public RandomAccessFile accessFile;
 // 線程的數量
 public static int threadNum = 3;
 // 每個線程負責下載的大小
 int blockSize;
 // 創建訪問的路徑
 public String path = "http://localhost:8080/doudou/youdao.exe";
 public static int threadCount;// 數量
 public void testDown() {
  try {
   // 創建出URL對象
   URL url = new URL(path);
   // 創建出 HttpURLConnection對象
   HttpURLConnection httpURLConnection = (HttpURLConnection) url
     .openConnection();
   // 設置 發請求發送的方式
   httpURLConnection.setRequestMethod("GET");
   // 設置請求是否超時時間
   httpURLConnection.setConnectTimeout(5000);
   // 設置
   httpURLConnection
     .setRequestProperty("User-Agent",
       " Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.2; Trident/6.0)");
   // 是否響應成功
   if (httpURLConnection.getResponseCode() == 200) {
    // 獲取文件的大小
    int size = httpURLConnection.getContentLength();
    System.out.println("文件的大小" + size);
    // 創建文件
    file = new File("youdao.exe");
    accessFile = new RandomAccessFile(file, "rwd");
    // 設置文件的大小
    accessFile.setLength(size);
    // 每個線程下載的大小
    blockSize = size / threadNum;
    // 開三個線程 操作此文件
    for (int i = 1; i <= threadNum; i++) {
     // 1 2 3
     // 計算出每個線程開始的位置
     int startSize = (i - 1) * blockSize;
     // 結束位置
     int endSize = (i) * blockSize;
     // 當線程是最后一個線程的時候
     if (i == threadNum) {
      // 判斷文件的大小是否大于計算出來的結束位置
      if (size > endSize) {
       // 結束位置 等于 文件的大小
       endSize = size;
      }
     }
     // 為每個線程創建一個隨機的讀取
     RandomAccessFile threadAccessFile = new RandomAccessFile(
       file, "rwd");
     new Thread(new DownLoadThread(i, threadAccessFile,
       startSize, endSize, path)).start();
    }
   }
  } catch (MalformedURLException e) {
   // TODO Auto-generated catch block
   e.printStackTrace();
  } catch (IOException e) {
   // TODO Auto-generated catch block
   e.printStackTrace();
  }
 }
 public static void main(String[] args) {
  DownLoadTest downLoadTest = new DownLoadTest();
  // 調用下載方法
  downLoadTest.testDown();
 }
}
class DownLoadThread implements Runnable {
 // 下載文件的封裝
 public RandomAccessFile accessFile; // 每個線程 都擁有一個accessFile的文件對象 線程1 線程2 線程3
 // 線程下載文件的起始位置
 public int startSize;
 public int endSize;
 // 文件下載的path路徑
 public String path;
 public int threadId; // 線程的標識
 public DownLoadThread(int threadId, RandomAccessFile accessFile,
   int startSize, int endSize, String path) {
  this.threadId = threadId;
  this.accessFile = accessFile;
  this.startSize = startSize;
  this.endSize = endSize;
  this.path = path;
 }
 @Override
 public void run() {
  // 執行run方法
  try {
   // 創建文件
   File threadFile = new File(threadId + ".txt");
   if (threadFile.exists()) {
    // 讀取該文件的內容
    // 創建文件的輸入流對象
    FileInputStream fis = new FileInputStream(threadFile);
    // 采用工具類讀取
    byte data[] = StreamTools.isToData(fis);
    // 轉化成字符串
    String threadLen = new String(data);
    if ((threadLen != null) && (!"".equals(threadLen))) {
     startSize = Integer.valueOf(threadLen);
     // 解決 416bug的錯誤
     if (startSize > endSize) {
      startSize = endSize - 1;
     }
    }
   }
   // 創建URL對象
   URL url = new URL(path);
   // 創建HttpURLConnection對象
   HttpURLConnection httpURLConnection = (HttpURLConnection) url
     .openConnection();
   // 設置請求的頭
   httpURLConnection.setRequestMethod("GET");
   // 設置請求是否超時時間
   httpURLConnection.setConnectTimeout(5000);
   // 設置
   httpURLConnection
     .setRequestProperty("User-Agent",
       " Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.2; Trident/6.0)");
   // 關鍵的設置
   httpURLConnection.setRequestProperty("Range", "bytes=" + startSize
     + "-" + endSize);
   // 輸出當前線程
   System.out.println("當前線程" + threadId + " 下載開始位置:" + startSize
     + " 下載結束位置:" + endSize);
   // 響應成功
   // 設置隨機讀取文件的 開始位置
   accessFile.seek(startSize);
   // 獲取相應流對象
   InputStream is = httpURLConnection.getInputStream();
   // 創建輸出流對象
   byte buffer[] = new byte[1024];
   int len = 0;
   int threadTotal = 0;// 每個線程下載后保存記錄 /
   while ((len = is.read(buffer)) != -1) {
    accessFile.write(buffer, 0, len);
    threadTotal += len;// 記錄你寫入的長度 //xml文件
    // 通過文件記錄文件下載的長度
    FileOutputStream fos = new FileOutputStream(threadFile);
    fos.write((threadTotal + "").getBytes());
    fos.flush();
    fos.close();
   }
   accessFile.close();
   is.close();
   System.out.println(threadId + "線程執行完畢");
   //線程操作
   synchronized (DownLoadTest.class) {
    DownLoadTest.threadCount++;
    if (DownLoadTest.threadCount >= DownLoadTest.threadNum) {
     for(int i=1;i<=DownLoadTest.threadNum;i++){
      File file = new File(i+".txt");
      if(file.exists()){
       file.delete();
      }
     }
    }
   }
  } catch (MalformedURLException e) {
   // TODO Auto-generated catch block
   e.printStackTrace();
  } catch (IOException e) {
   // TODO Auto-generated catch block
   e.printStackTrace();
  }
 }
}

2.流工具的封裝 StreamTools.java

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
package www.csdn.net.down;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
public class StreamTools {
 public static byte[] isToData(InputStream is) throws IOException{
  // 字節輸出流
  ByteArrayOutputStream bops = new ByteArrayOutputStream();
  // 讀取數據的緩存區
  byte buffer[] = new byte[1024];
  // 讀取長度的記錄
  int len = 0;
  // 循環讀取
  while ((len = is.read(buffer)) != -1) {
   bops.write(buffer, 0, len);
  }
  // 把讀取的內容轉換成byte數組
  byte data[] = bops.toByteArray();
  bops.flush();
  bops.close();
  is.close();
  return data;
 }
}

希望本文所述對大家Java程序設計有所幫助。

延伸 · 閱讀

精彩推薦
主站蜘蛛池模板: 欧美香蕉| 天天干天天色综合 | 俄罗斯年轻男同gay69 | 污漫日本E同人 | 精品国产三级av在线 | 好爽好深好猛好舒服视频上 | 厨房play黄瓜进去小说h | 国产一卡 | 欧美精品日韩一区二区三区 | 超91在线| 5x社区发源地最新地址 | 果冻传媒在线免费观看 | 国产成人99精品免费观看 | 久久精品亚洲热综合一本 | 教师波多野结衣在线播放 | 非洲黑人xxxxxbbbbb | 91香蕉国产在线观看免费永久 | 国产激情视频 | 五月婷婷伊人网 | 亚洲精品久久久成人 | 精品人伦一区二区三区潘金莲 | 手机在线免费观看高清 | 国产91素人搭讪系列天堂 | 精品湿 | 五月性| 精品AV亚洲乱码一区二区 | 国产高清dvd | 欧美伊人影院 | 成人高清视频在线观看 | 把美女屁股眼扒开图片 | 亚洲男人的天堂在线 | 国产馆| 九九精品免视频国产成人 | 99在线视频精品 | 天天操天天爽天天射 | 欧洲老妇人70 | 日本在线视| 草莓视频旧版 | 国产精品嫩草影院一二三区入口 | 色cccwww| 91久久碰国产 |