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

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

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程序設計有所幫助。

延伸 · 閱讀

精彩推薦
主站蜘蛛池模板: 99久久精品免费看国产 | 国产日韩高清一区二区三区 | 调教全程肉动画片在线观看 | 日本mv精品中文字幕 | 亚洲视频在线观看免费 | 色先锋 影音先锋a 资源站 | 日本在线不卡免 | tobu8在线观看免费高清 | 999精品视频在线观看 | 欧美在线视频一区 | 欧美xxxbrazzers| 成人福利网站 | 国色天香社区在线 | 免费永久视频 | 福利社在线免费观看 | 免费国产成人高清视频网站 | 午夜欧美精品 | 日本不卡免费新一二三区 | 2020国产精品亚洲综合网 | 免费毛片大全 | 天天爱天天操天天射 | 羞羞视频免费观看网站 | www.麻豆视频| 亚洲精品乱码久久久久久蜜桃 | 九九大香尹人视频免费 | 欧美日韩亚洲国内综合网俺 | 18young第一次 | 午夜人妻理论片天堂影院 | 日韩成人在线免费视频 | 成品人视频免费观看 | 亚洲第一区欧美日韩精品 | 四虎最新永久免费网址 | 亚洲日本aⅴ片在线观看香蕉 | 亚洲AV无码专区国产乱码网站 | 好紧好爽再叫浪一点点潘金莲 | 男人看片网址 | 亚洲国产欧美在线人网站 | 国产黄频在线观看高清免费 | 我要看靠逼片 | 国产一区二区不卡视频 | 久久精品无码一区二区日韩av |