Java多線程下載的實(shí)現(xiàn)方法
package cn.me.test;
import java.io.InputStream;
import java.io.RandomAccessFile;
import java.net.HttpURLConnection;
import java.net.URL;
/**
* 多線程下載
* 1:使用RandomAccessFile在任意的位置寫入數(shù)據(jù)。
* 2:需要計(jì)算第一個(gè)線程下載的數(shù)據(jù)量,可以平均分配。如果不夠平均時(shí),
* 則直接最后一個(gè)線程處理相對(duì)較少的數(shù)據(jù)
* 3:必須要在下載之前準(zhǔn)備好相同大小的文件,通過文件頭獲取
*/
public class MultiThreadDownload {
public static void main(String[] args) throws Exception {
//1:聲明文件名和下載的地址
String fileName = "aa.rar";
String urlStr = "http://localhost:7777/day18";
//2:聲明Url
URL url = new URL(urlStr+"/"+fileName);
//3:獲取連接
HttpURLConnection con =
(HttpURLConnection) url.openConnection();
//4:設(shè)置請(qǐng)求方式
con.setRequestMethod("GET");
//5:獲取請(qǐng)求頭,即文件的長(zhǎng)度
int length = con.getContentLength();//獲取下載文件的長(zhǎng)度,以計(jì)算每個(gè)線程應(yīng)該下載的數(shù)據(jù)量。
//6:在指定的目錄下,創(chuàng)建一個(gè)同等大小的文件
RandomAccessFile file = new RandomAccessFile("d:/a/"+fileName, "rw");//創(chuàng)建一個(gè)相同大小的文件。
//7:設(shè)置文件大小,占位
file.setLength(length);//設(shè)置文件大小。
file.close();
//8:定義線程個(gè)數(shù)
int size = 3;
//9:計(jì)算每一個(gè)線程應(yīng)該下載多少字節(jié)的數(shù)據(jù),如果正好整除則最好,否則加1
int block = length/size==0?length/size:length/size+1;//計(jì)算每個(gè)線程應(yīng)該下載的數(shù)據(jù)量。
System.err.println("每個(gè)線程應(yīng)該下載:"+block);
//10:運(yùn)行三個(gè)線程并計(jì)算從哪個(gè)字節(jié)開始到哪一個(gè)字節(jié)結(jié)束
for(int i=0;i<size;i++){
int start = i*block;
int end = start+(block-1);//計(jì)算每一個(gè)線程的開始和結(jié)束字節(jié)。
System.err.println(i+"="+start+","+end);
new MyDownThread(fileName, start, end,url).start();
}
}
static class MyDownThread extends Thread{
//定義文件名
private String fileName;
//定義從何地開始下載
private int start;
//定義下載到哪一個(gè)字節(jié)
private int end;
private URL url;
public MyDownThread(String fileName,int start,int end,URL url){
this.fileName=fileName;
this.start=start;
this.end=end;
this.url=url;
}
@Override
public void run() {
try{
//11:開始下載
HttpURLConnection con =
(HttpURLConnection) url.openConnection();
con.setRequestMethod("GET");
//12:設(shè)置分段下載的請(qǐng)求頭
con.setRequestProperty("Range","bytes="+start+"-"+end);//設(shè)置從服務(wù)器上讀取的文件塊。
//13:開始下載,需要判斷206
if(con.getResponseCode()==206){//訪問成功,則返回的狀態(tài)碼為206。
InputStream in = con.getInputStream();
//14:聲明隨機(jī)寫文件對(duì)象,注意rwd是指即時(shí)將數(shù)據(jù)寫到文件中,而不使用緩存區(qū)
RandomAccessFile out = new RandomAccessFile("d:/a/"+fileName,"rwd");
out.seek(start);//設(shè)置從文件的某個(gè)位置開始寫數(shù)據(jù)。
byte[] b=new byte[1024];
int len = 0;
while((len=in.read(b))!=-1){
out.write(b,0,len);
}
out.close();
in.close();
}
System.err.println(this.getName()+"執(zhí)行完成");
}catch(Exception e){
throw new RuntimeException(e);
}
}
}
}
相關(guān)文章
spring boot集成rabbitmq的實(shí)例教程
這篇文章主要給大家介紹了關(guān)于spring boot集成rabbitmq的相關(guān)資料,springboot集成RabbitMQ非常簡(jiǎn)單,文中通過示例代碼介紹的非常詳細(xì),需要的朋友們可以參考借鑒,下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧。2017-11-11
Java基礎(chǔ)之switch分支結(jié)構(gòu)詳解
這篇文章主要介紹了Java基礎(chǔ)之switch分支結(jié)構(gòu)詳解,文中有非常詳細(xì)的代碼示例,對(duì)正在學(xué)習(xí)java的小伙伴們有很大的幫助,需要的朋友可以參考下2021-05-05
Java后端向前端返回文件流實(shí)現(xiàn)下載功能的方法
這篇文章主要給大家介紹了關(guān)于Java后端向前端返回文件流實(shí)現(xiàn)下載功能的相關(guān)資料,Java后端可以通過調(diào)用接口返回文件流來實(shí)現(xiàn)文件傳輸功能,文中通過代碼介紹的非常詳細(xì),需要的朋友可以參考下2023-10-10
使用 Apache POI 在 Java 中寫入 Excel
這篇文章詳細(xì)介紹了如何使用ApachePOI在Java中編寫Excel文件的技巧,包括創(chuàng)建工作簿、工作表、行和單元格,以及如何處理不同版本的Excel文件,通過詳細(xì)的步驟和代碼示例,讀者可以快速掌握ApachePOI的基本使用方法,感興趣的朋友一起看看吧2025-02-02
解決SpringBoot項(xiàng)目啟動(dòng)成功但接口訪問404的問題
這篇文章主要介紹了如何解決SpringBoot項(xiàng)目啟動(dòng)成功但接口訪問404的問題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,接下來就跟著小編一起來看看吧2023-07-07
SpringBoot使用Flyway進(jìn)行數(shù)據(jù)庫(kù)管理的操作方法
Flyway是一個(gè)開源的數(shù)據(jù)庫(kù)版本管理工具,并且極力主張“約定大于配置”,簡(jiǎn)單、專注、強(qiáng)大。接下來通過本文給大家介紹SpringBoot使用Flyway進(jìn)行數(shù)據(jù)庫(kù)管理的方法,感興趣的朋友一起看看吧2021-09-09
SpringCloud如何根據(jù)服務(wù)名獲取服務(wù)運(yùn)行實(shí)例并進(jìn)行負(fù)載均衡
文章介紹了SpringCloud中使用Nacos作為注冊(cè)中心時(shí),服務(wù)注冊(cè)和發(fā)現(xiàn)的過程,以及如何通過DiscoveryClient接口和LoadBalancerClient類進(jìn)行服務(wù)的負(fù)載均衡,感興趣的朋友跟隨小編一起看看吧2025-01-01

