多线程下载是通过占有服务器资源来提高速度的。
每个线程应该下载一个文件的不同位置,假如现在有一个长度为10的资源,有三个线程,那么第一个线程下载的长度为012,第二个为345,第四个为6789
所以问题来了每个线程下载的长度是多少呢?
线程的id为0,1,2
每个线程下载的数量=总长度/线程数量
size=10/3
start:id*size
end:(id+1)*size-1
最后一个线程的结束位置为:总长度-1
package down; import java.io.File; import java.io.InputStream; import java.io.RandomAccessFile; import java.net.HttpURLConnection; import java.net.URL; public class Down { static int threadCount = 3; static String path = "http://192.168.21.1:8080/ok/ideaIU-14.1.3.exe"; /** * @param args */ public static void main(String[] args) { try { URL url = new URL(path); HttpURLConnection conn = (HttpURLConnection) url.openConnection(); conn.setRequestMethod("GET"); conn.setReadTimeout(5000); conn.setConnectTimeout(5000); if(conn.getResponseCode()==200){ //第一次请求要下载的长度 int length = conn.getContentLength(); //应该从字符串中截取文件名称 File file = new File("ideaIU-14.1.3.exe"); //在下载之前生成临时文件,占位置 RandomAccessFile rdm = new RandomAccessFile(file, "rwd"); //给临时文件大小 rdm.setLength(length); //关闭 rdm.close(); //计算每个线程应该下载的长度 int size = length/threadCount; //为每个线程分配开始位置和结束位置 for (int i = 0; i <threadCount; i++) { int start = i*size; int end = (i+1)*size-1; //最后一个线程的结束位置为总长度 if(i==threadCount-1){ end= length; } System.out.println(i+"线程下载区间"+start+"---"+end); //每次都调用新的线程 new DownThread(start, end, i).start(); } } } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } } } //线程 class DownThread extends Thread{ private int start; private int end; private int threadId; public DownThread(int start, int end, int threadId) { this.start = start; this.end = end; this.threadId = threadId; } @Override public void run() { try { //再次请求网络 URL url = new URL(Down.path); HttpURLConnection conn = (HttpURLConnection) url.openConnection(); conn.setRequestMethod("GET"); conn.setReadTimeout(5000); conn.setConnectTimeout(5000); //设置本次请求的文件的长度 conn.setRequestProperty("Range","bytes="+start+"-"+end); //请求部分数据是206 if(conn.getResponseCode()==206){ //得到请求长度的文件输入流 InputStream is = conn.getInputStream(); byte[] b = new byte[1024]; int len = 0; //记录每一次下载字节数 int totle =0; //应该从字符串中截取文件名称 File file = new File("ideaIU-14.1.3.exe"); //拿到之前占位置那个文件,相当于输出流 RandomAccessFile rdm = new RandomAccessFile(file, "rwd"); //改变写入文件的开始位置 rdm.seek(start); while((len=is.read(b))!=-1){ //每次读取流里的数据写到临时文件里 rdm.write(b, 0, len); totle += len; System.out.println(threadId+"线程"+"下载了"+totle); } rdm.close(); } } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } } }