本文出自:《疯狂java讲义第3版本》第十七章
下载url文件,并不是线程越多,下载的越快,一定是有一个最佳的方案。
测试经过:path为20M的MP3文件 , 用1个线程用时:13197ms;用2个线程用时8560ms;用3个线程用时:13894ms;用4个线程用时16648ms;
具体还是要根据项目环境做选择。
import java.io.BufferedInputStream; import java.io.IOException; import java.io.InputStream; import java.io.RandomAccessFile; import java.net.HttpURLConnection; import java.net.URL; import java.util.Date; /** * 多线程下载工具 */ public class DownUtil { private String path; //下载文件的路径 private String targetFile; //文件保存的位置 private int threadNum; //下载资源的线程数 private DownThread[] threads; //线程数组 private int fileSize; //文件的字节数 public DownUtil(String path, String targetFile, int threadNum) { this.path = path; this.targetFile = targetFile; this.threadNum = threadNum; threads = new DownThread[threadNum]; } public void download() throws IOException { URL url = new URL(path); HttpURLConnection conn = (HttpURLConnection) url.openConnection(); conn.setConnectTimeout(5 * 1000); conn.setRequestMethod("GET"); fileSize = conn.getContentLength(); conn.disconnect(); int currentPartSize = fileSize / threadNum + 1; RandomAccessFile file = new RandomAccessFile(targetFile, "rw"); file.setLength(fileSize); //设置文件大小 file.close(); for (int i = 0; i < threadNum; i++) { //计算每个线程开始下载的位置 int startPos = i * currentPartSize; //每一个线程使用一个RandomAccessFile下载 RandomAccessFile currentPart = new RandomAccessFile(targetFile, "rw"); //定位该线程的下载位置 currentPart.seek(startPos); //创建下载线程 threads[i] = new DownThread(startPos, currentPartSize, currentPart); //启动下载线程 threads[i].start(); } } /** * 获取下载百分比 */ public double getCompleteRate() { int sumSize = 0; for (int i = 0; i < threadNum; i++) { sumSize += threads[i].length; } return sumSize * 1.0 / fileSize; } private class DownThread extends Thread { private int startPos; //当前线程的下载位置 private int currentPartSize; //当前线程需要负责的大小 private RandomAccessFile currentPart; //当前线程需要下载的文件块 private int length; //该文件已下载的字节数 public DownThread(int startPos, int currentPartSize, RandomAccessFile currentPart) { this.startPos = startPos; this.currentPartSize = currentPartSize; this.currentPart = currentPart; } public void run() { try { URL url = new URL(path); HttpURLConnection conn = (HttpURLConnection) url.openConnection(); conn.setConnectTimeout(5 * 1000); conn.setRequestMethod("GET"); InputStream in = conn.getInputStream(); BufferedInputStream bis = new BufferedInputStream(in); bis.skip(startPos); byte[] buff = new byte[1024]; int hasRead = 0; while (length < currentPartSize && (hasRead = bis.read(buff)) != -1) { currentPart.write(buff, 0, hasRead); length += hasRead; } currentPart.close(); bis.close(); in.close(); } catch (IOException e) { e.printStackTrace(); } } } public static void main(String[] args) throws IOException { DownUtil downUtil = new DownUtil("http://www.ytmp3.cn/down/57196.mp3", "G:/57196.mp3", 2); long start = new Date().getTime(); downUtil.download(); new Thread(() -> { while (downUtil.getCompleteRate() < 1) { long end = new Date().getTime(); System.out.println("已完成:"+(end -start) +"ms"+ downUtil.getCompleteRate()); try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } } }).start(); } }