每日一讲
我不知道我应当成为一个什么样的人,但我知道我应当不成为什么样的人!
目录
3.2创建CountDownLatch类及调用MergeFile类
1.多线程文件分区下载目的和原理
目的:正常我们下载文件通常是一下到底,只使用一个线程进行下载。但是通常情况下使用多个线程下载的效率会更高,迅雷下载中也是推荐使用三个线程进行下载,当然这也取决于网络,网络不好,线程多也未必是好事。
原理:将一个文件分成多端进行下载,每个线程下载文件的一部分,就好比一个苹果咱们三个好基友一起吃。用这么一张图就能很好的了解了。
2.多线程文件下载的实现过程
实际上想要实现简单的多线程任务设计的技术不难,但也有许多,比如多线程、I/O流、参数传递、构造函数、类和对象等等。
文件链接:https://dldir1.qq.com/qqfile/qq/QQNT/Windows/QQ_9.9.7_240305_x64_01.exe
2.1获取下载文件的大小
要分区间下载我们就必然要文件的总大小,才能更好的分配嘛。
URL url =new URL(address);
HttpURLConnection httpURLConnection= (HttpURLConnection) url.openConnection();
long fileSize=httpURLConnection.getContentLengthLong();//获取要下载文件的大小
System.out.println("文件大小为:"+fileSize);
2.2计算每个线程需要下载的范围
既然大厨小林煮好一锅饭了,那么必然要合理的分配好每个小朋友要吃的饭咯。
long size=fileSize/threadNum;//每个线程下载的部分
//startPos:起始位置 endPos:结束位置
for(int i=0;i<threadNum;i++)
{
long startPos= i* size;
long endPos;
if(i==threadNum-1){
endPos=0;
}else{
endPos=startPos+size;
}
if(startPos!=0){
startPos++;
}
System.out.println("第"+(i+1)+"个线程下载的区间为:"+startPos+"----"+endPos);
}
2.3创建线程进行下载任务
哥们,饭已经给你分完了,那接下来就是吃光这包分配的饭勒。
//每循环一次就启动一个线程
DownloadThread downloadThread=new DownloadThread(startPos,endPos,url,i+1,address,threadNum,countDownLatch);
downloadThread.start();
class DownloadThread extends Thread{
long startPos;
long endPos;
URL url;
int index;
String address;
int threadNum;
CountDownLatch countDownLatch;
//创建构造函数传递参数进来,(需要哪些参数就传哪些过来)
public DownloadThread(long startPos,long endPos,URL url,int index,String address,int threadNum,CountDownLatch countDownLatch)
{
this.startPos=startPos;
this.endPos=endPos;
this.url=url;
this.index=index;
this.address=address;
this.threadNum=threadNum;
this.countDownLatch=countDownLatch;
}
public void run(){
}
}
2.4在线程内进行读写操作实现文件下载
虽然说饭已经吃下去了,但是哥们得消化呀,光吃不拉早晚得成小胖呀,那么接下来我们就需要进行文件下载咯,先读后写,先读后写,先读后写--IO流秘诀可不能忘。
//文件下载--先读后写
try {
//这里用于断点续传,每次只请求文件的一部分
URLConnection urlConnection = (HttpURLConnection) url.openConnection();
if(index!=threadNum){
urlConnection.setRequestProperty("Range","byte="+startPos+"-"+endPos);
}else{
urlConnection.setRequestPro