【转自】
光仔December
问题:多线程下载的好处?
多线程下载比单线程下载快,主要的原因是采用多线程下载,可以抢占更多的服务器资源。抢占Cpu的处理空间,实现更快的下载速度
问题:多线程下载位置的确定?
开启N条线程下载文件,假设文件大小为buf,那么每条线程的下载量为:
buf%N==0?buf/N:buf/N+1;
那么,每一条线程应该从网络文件的什么位置开始下载??
假设线程id号threadid为0,1,2,每一条线程下载的数据量为block=4
第一个文件从threadid*block开始下载,结束位置(threadid+1)*block-1
所以公式为:
int start=threadid*block;
int end=(threadid+1)*block-1;
多线程下载源码(仅供参考)
- package cn.deu.hpu.download;
- import java.io.File;
- import java.io.InputStream;
- import java.io.RandomAccessFile;
- import java.net.HttpURLConnection;
- import java.net.URL;
- public class MulThreadDownLoad {
- public static void main(String[] args) throws Exception{
- String path="http://192.168.111.104:8080/web/gg.jpg";
- new MulThreadDownLoad().download(path,3);
- }
- /*下载文件
- * path 网络文件路径
- * */
- public void download(String path,int threadsize)throws Exception{
- URL url=new URL(path);
- HttpURLConnection conn=(HttpURLConnection) url.openConnection();
- conn.setConnectTimeout(5000);
- conn.setRequestMethod("GET");
- if(conn.getResponseCode()==200){
- //取得网络文件的长度
- int length=conn.getContentLength();
- File file=new File(getFilename(path));
- //随机访问文件类(生成一个与网络文件长度相等的本地文件)
- RandomAccessFile accessFile=new RandomAccessFile(file, "rwd");
- accessFile.setLength(length);
- accessFile.close();
- //计算每条线程需要下载的数据量
- int block=length%threadsize==0?length/threadsize:length/threadsize+1;
- for (int threadid = 0; threadid< threadsize; threadid++) {
- new DownloadThread(threadid,block,url,file).start();
- }
- }else{
- System.out.println("下载失败!");
- }
- }
- private String getFilename(String path) {
- //从URL地址的最后一个"/"后开始记录文件名
- return path.substring(path.lastIndexOf("/")+1);
- }
- private class DownloadThread extends Thread{
- private int threadid;
- private int block;
- private URL url;
- private File file;
- public DownloadThread(int threadid,int block,URL url,File file){
- this.threadid=threadid;
- this.block=block;
- this.url=url;
- this.file=file;
- }
- public void run(){
- //计算该线程从网络文件的什么位置开始下载
- int start=threadid*block;
- //下载到网络文件的什么位置结束
- int end=(threadid+1)*block-1;
- try {
- RandomAccessFile accessFile = new RandomAccessFile(file, "rwd");
- //从某一个位置开始写入数据
- accessFile.seek(start);
- HttpURLConnection conn=(HttpURLConnection) url.openConnection();
- conn.setConnectTimeout(5000);
- conn.setRequestMethod("GET");
- //指定行网络文件的某个区域下载数据(开始位置-结束位置)
- conn.setRequestProperty("Range", "bytes="+start+"-"+end);
- //请求某一段数据的话,请求码不是200,是206
- if(conn.getResponseCode()==206){
- InputStream instream=conn.getInputStream();
- byte [] buffer=new byte[1024];
- int len=0;
- while((len=instream.read(buffer))!=-1){
- accessFile.write(buffer,0,len);
- }
- accessFile.close();
- instream.close();
- }
- System.out.println("第"+(threadid+1)+"线程已经下载完成");
- } catch (Exception e) {
- e.printStackTrace();
- }
- }
- }
- }
package cn.deu.hpu.download; import java.io.File; import java.io.InputStream; import java.io.RandomAccessFile; import java.net.HttpURLConnection; import java.net.URL; public class MulThreadDownLoad { public static void main(String[] args) throws Exception{ String path="http://192.168.111.104:8080/web/gg.jpg"; new MulThreadDownLoad().download(path,3); } /*下载文件 * path 网络文件路径 * */ public void download(String path,int threadsize)throws Exception{ URL url=new URL(path); HttpURLConnection conn=(HttpURLConnection) url.openConnection(); conn.setConnectTimeout(5000); conn.setRequestMethod("GET"); if(conn.getResponseCode()==200){ //取得网络文件的长度 int length=conn.getContentLength(); File file=new File(getFilename(path)); //随机访问文件类(生成一个与网络文件长度相等的本地文件) RandomAccessFile accessFile=new RandomAccessFile(file, "rwd"); accessFile.setLength(length); accessFile.close(); //计算每条线程需要下载的数据量 int block=length%threadsize==0?length/threadsize:length/threadsize+1; for (int threadid = 0; threadid< threadsize; threadid++) { new DownloadThread(threadid,block,url,file).start(); } }else{ System.out.println("下载失败!"); } } private String getFilename(String path) { //从URL地址的最后一个"/"后开始记录文件名 return path.substring(path.lastIndexOf("/")+1); } private class DownloadThread extends Thread{ private int threadid; private int block; private URL url; private File file; public DownloadThread(int threadid,int block,URL url,File file){ this.threadid=threadid; this.block=block; this.url=url; this.file=file; } public void run(){ //计算该线程从网络文件的什么位置开始下载 int start=threadid*block; //下载到网络文件的什么位置结束 int end=(threadid+1)*block-1; try { RandomAccessFile accessFile = new RandomAccessFile(file, "rwd"); //从某一个位置开始写入数据 accessFile.seek(start); HttpURLConnection conn=(HttpURLConnection) url.openConnection(); conn.setConnectTimeout(5000); conn.setRequestMethod("GET"); //指定行网络文件的某个区域下载数据(开始位置-结束位置) conn.setRequestProperty("Range", "bytes="+start+"-"+end); //请求某一段数据的话,请求码不是200,是206 if(conn.getResponseCode()==206){ InputStream instream=conn.getInputStream(); byte [] buffer=new byte[1024]; int len=0; while((len=instream.read(buffer))!=-1){ accessFile.write(buffer,0,len); } accessFile.close(); instream.close(); } System.out.println("第"+(threadid+1)+"线程已经下载完成"); } catch (Exception e) { e.printStackTrace(); } } } }
转载请注明出处!程序猿之洞:http://blog.csdn.net/acmman