Java多線程下載文件實(shí)現(xiàn)案例詳解
原理解析:
利用RandomAccessFile在本地創(chuàng)建一個(gè)隨機(jī)訪問(wèn)文件,文件大小和服務(wù)器要下載的文件大小相同。 根據(jù)線程的數(shù)量(假設(shè)有三個(gè)線程),服務(wù)器的文件三等分,并把我們?cè)诒镜貏?chuàng)建的文件同樣三等分,每個(gè)線程下載自己負(fù)責(zé)的部分,到相應(yīng)的位置即可。
示例圖:

代碼如下
import java.io.InputStream;
import java.io.RandomAccessFile;
import java.net.HttpURLConnection;
import java.net.URL;
public class MutilDownload {
private static String path = "http://192.168.80.85:8080/test.doc";
private static final int threadCount = 3;
public static void main(String[] args) {
try {
URL url = new URL(path);
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setRequestMethod("GET");
conn.setConnectTimeout(5000);
int responseCode = conn.getResponseCode();
if (responseCode == 200) {
int contentLength = conn.getContentLength();
System.out.println("length" + contentLength);
RandomAccessFile rafAccessFile = new RandomAccessFile("test.doc", "rw");
rafAccessFile.setLength(contentLength);
int blockSize = contentLength / threadCount;
for (int i = 0; i < threadCount; i++) {
int startIndex = i * blockSize; //每個(gè)現(xiàn)成下載的開(kāi)始位置
int endIndex = (i + 1) * blockSize - 1;// 每個(gè)線程的結(jié)束位置
if (i == threadCount - 1) {
//最后一個(gè)線程
endIndex = contentLength - 1;
}
new DownloadThread(startIndex, endIndex, i).start();
}
}
} catch (Exception e) {
}
}
private static class DownloadThread extends Thread {
private int startIndex;
private int endIndex;
private int threadId;
public DownloadThread(int startIndex, int endIndex, int threadId) {
this.startIndex = startIndex;
this.endIndex = endIndex;
this.threadId = threadId;
}
@Override
public void run() {
try {
URL url = new URL(path);
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setRequestMethod("GET");
conn.setConnectTimeout(5000);
conn.setRequestProperty("Range", "bytes=" + startIndex + "-" + endIndex); //固定寫(xiě)法,請(qǐng)求部分資源
int responseCode = conn.getResponseCode(); // 206表示請(qǐng)求部分資源
if (responseCode == 206) {
RandomAccessFile rafAccessFile = new RandomAccessFile("test.doc", "rw");
rafAccessFile.seek(startIndex);
InputStream is = conn.getInputStream();
int len = -1;
byte[] buffer = new byte[1024];
while ((len = is.read(buffer)) != -1) {
rafAccessFile.write(buffer, 0, len);
}
rafAccessFile.close();
System.out.println("線程" + threadId + "下載完成");
}
} catch (Exception e) {
}
}
}
}
以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
Elasticsearch term 查詢之精確值搜索功能實(shí)現(xiàn)
term查詢是Elasticsearch中用于精確值搜索的一種基本方式,通過(guò)了解 term 查詢的工作原理和使用方法,你可以更好地利用 Elasticsearch 進(jìn)行結(jié)構(gòu)化數(shù)據(jù)的搜索和分析,本文將詳細(xì)介紹 term 查詢的工作原理、使用場(chǎng)景以及如何在 Elasticsearch 中應(yīng)用它,感興趣的朋友一起看看吧2024-06-06
基于java中的流程控制語(yǔ)句總結(jié)(必看篇)
下面小編就為大家?guī)?lái)一篇基于java中的流程控制語(yǔ)句總結(jié)(必看篇)。小編覺(jué)得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2017-06-06
Spring Boot 捕捉全局異常 統(tǒng)一返回值的問(wèn)題
這篇文章主要介紹了Spring Boot 捕捉全局異常 統(tǒng)一返回值,本文通過(guò)實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2020-06-06
java實(shí)現(xiàn)Runnable接口適合資源的共享
這篇文章主要為大家詳細(xì)介紹了java實(shí)現(xiàn)Runnable接口適合資源的共享,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2018-07-07
Spring Boot創(chuàng)建可執(zhí)行jar包的實(shí)例教程
這篇文章主要介紹了Spring Boot創(chuàng)建可執(zhí)行jar包的實(shí)例教程,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2018-02-02

