多线程下载简单实现
多线程下载简单实现
1、多线程下载原理
将网络上待下载的文件,划分为几段,然后对应开几条线程分别对应划分好的段,分别进行下载。如下图:
2、多线程文件下载注意点
这里主要还是分段需注意下起始位置和终止位置。这里我们的处理是:
先取出文件的大小:size = con.getContentLength();然后再进行下面分段的长度测量:int block = size%threadNum==0?size/threadNum:size/threadNum+1;这样我们保证分成的几段长度加起来大于或等于待下载文件的长度。
下面是代码:
package org.hwq.multhreaddownload;import java.io.FileNotFoundException;import java.io.IOException;import java.io.InputStream;import java.io.RandomAccessFile;import java.net.HttpURLConnection;import java.net.URL;public class MulThreadDownload2 {//开启的线程数public static final int threadNum = 3;public void download() throws IOException{//下载文件的网络路径URL url = new URL("http://localhost:8080/Thunder.exe");//打开网络连接HttpURLConnection con = (HttpURLConnection) url.openConnection();//获取待下载文件的大小int remoteFileSize = con.getContentLength();//定义下载完成后保存的文件RandomAccessFile file = new RandomAccessFile("d:\\Thunder.exe","rwd");//将文件的长度设置成待下载文件的大小file.setLength(remoteFileSize);//将待下载文件分段int block = remoteFileSize%threadNum==0?remoteFileSize/threadNum:remoteFileSize/threadNum+1;//启动线程,开始下载for(int i=0;i<threadNum;i++){new MyThread(block*i,block,"d:\\Thunder.exe",url).start();}}class MyThread extends Thread{URL url;//待下载文件路径int start;//下载开始点int block;//分段的长度RandomAccessFile file;//下载后保存的文件MyThread(int start,int block,String file,URL url) throws FileNotFoundException{this.start = start;this.block = block;//这个地方需注意,必须让每条线程,独立开启文件,不然对同一个文件进行操作,会出导致出错this.file = new RandomAccessFile(file,"rwd");this.url = url;}public void run(){try {//重新分别打开下载路径HttpURLConnection con = (HttpURLConnection) url.openConnection();con.setRequestMethod("GET");//获取分段后要下载的数据con.setRequestProperty("Range", "bytes=" + start + "-" + (start+block-1));//获取待下载文件输入流InputStream in = con.getInputStream();//缓冲区byte[] b = new byte[1024];int len = -1;//将保存文件开始下载起点移到同待下载文件读取数据的起始点(不设置会出问题)file.seek(start);while((len = in.read(b))!=-1){//将下载的数据写入保存文件file.write(b, 0, len);}//关闭文件file.close();//关闭输入流in.close();} catch (Exception e) {e.printStackTrace();}}}public static void main(String[] args) throws IOException {MulThreadDownload2 d = new MulThreadDownload2();d.download();}}过程中很悲催的不知道这个方法:
con.setRequestProperty("Range", "bytes=" + start + "-" + (start+block-1));可以获得远程文件分段,结果自己写了个(其实是仿照InputStream源码的skip()方法),记录下来:
int block = size%threadNum==0?size/threadNum:size/threadNum+1;public int read(InputStream in,byte[] b){try{if(block==0)return -1;int c = in.read();if(c == -1)return -1;block--;b[0] = (byte) c;int i = 1;for(;i<b.length&&block>0;i++){c = in.read();if(c == -1)break;block--;b[i] = (byte) c;}return i;}catch (Exception e) {e.printStackTrace();}return -1;}最后,有几个点不明白:
HttpURLConnection,URLConnection中的下面方法看不懂,希望有懂得的朋友讲解下:
public String getHeaderField(String name) { return null; }public String getHeaderFieldKey(int n) { return null; }public String getHeaderField(int n) { return null; }.......为什么直接返回null了。但是程序还能执行下去。小弟实在不解啊。 1 楼 listen1984 2012-06-14 HttpURLConnection是个abstract class,真正调用的是URLConnection中的方法。
另外千万不要用skip那个办法,那样的话不会节省时间,反而增加下载所需时间。 2 楼 uuubd 2012-06-18 listen1984 写道HttpURLConnection是个abstract class,真正调用的是URLConnection中的方法。
另外千万不要用skip那个办法,那样的话不会节省时间,反而增加下载所需时间。
listen1984 写道HttpURLConnection是个abstract class,真正调用的是URLConnection中的方法。
另外千万不要用skip那个办法,那样的话不会节省时间,反而增加下载所需时间。
这个有什么原因吗?想知道下。