多线程下载就是把网络上的资源文件划分成多块,然后把每一块分别分给一个线程去下载,下载也就是用InputStream读取资源,然后用RandomAccessFile来实现保存到本地。
由于需要请求网络资源,本地断网所以在本机测试用Tomcat,在eclipse创建一个工程t2,启动服务器,然后去下载b.mp3:
测试类:
package t2; public class DownloadTest { public static void main(String[] args) { DownloadTool.resourceDownload("http://localhost:8080/t2/raw/b.mp3"); } }
下载工具类:
package t2; import java.io.IOException; import java.io.RandomAccessFile; import java.net.*; public class DownloadTool { public static void resourceDownload(String path) { try { int startPosition = 0;//记录写入文件时的起始位置 int threadCount = 4;//线程数量 URL url = new URL(path); HttpURLConnection conn = (HttpURLConnection) url.openConnection();//打开连接 conn.setRequestMethod("GET");//设置为get请求 conn.setConnectTimeout(6*1000); conn.setRequestProperty("range", "bytes="+startPosition+"-"); int fileSize = conn.getContentLength();//获取网络资源的大小 int block = fileSize/threadCount+1;//计算每个线程所读取的块的大小 String filename = path.substring(path.lastIndexOf("/")+1);//获取网络资源的文件名 // System.out.println(filename); // System.out.println("fileSize= "+fileSize); RandomAccessFile ras = new RandomAccessFile("f:/download/"+filename, "rw");//新建文件,保存在本地 ras.setLength(fileSize);//设置新建文件的大小 ras.close(); //创建4个线程来下载网络资源 for(int i=0;i<threadCount;i++) { //保存每一个线程下载的block到file RandomAccessFile file = new RandomAccessFile("f:/download/"+filename,"rw"); startPosition = i*block;//计算写入文件的起始位置 file.seek(startPosition);//把文件指针已到起始位置 System.out.println("the num "+i+" thread started"); new DownloadThread(i,block,url,file).start();//启动线程 } conn.disconnect(); } catch (MalformedURLException e) { e.printStackTrace(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } }
下载线程类:
package t2; import java.io.*; import java.net.*; public class DownloadThread extends Thread{ private int i; private int block; private URL url; private RandomAccessFile file; public DownloadThread(int i,int block,URL url,RandomAccessFile file) { this.i = i; this.block = block; this.url = url; this.file = file; } @Override public void run() { try { HttpURLConnection conn = (HttpURLConnection) url.openConnection();//打开连接 conn.setReadTimeout(6*1000); conn.setRequestMethod("GET"); InputStream is = conn.getInputStream();//从连接获取InputStream byte[] buf = new byte[1024];//读取的缓冲区 int readSize = 0;//记录线程所读的块大小 int len = 0; System.out.println("bloack"+i+"= "+block); while((len=is.read(buf))>0 && readSize<block) {//线程下载文件结束的条件之一是readSize<block file.write(buf, 0, len); readSize += len; } System.out.println("the num " + i +" thread finished download"); file.close(); is.close(); conn.disconnect(); } catch (IOException e) { e.printStackTrace(); } } }