开三个线程下载,代码:
package demo; import java.io.InputStream; import java.io.RandomAccessFile; import java.net.HttpURLConnection; import java.net.URL; public class MutilDownLoad { // 放在Tomcat下的一个文件 static String path = "http://192.168.87.1:8080/lol.exe"; // 多线程的个数(开3个线程) private static final int THREADACOUNT = 3; public static void main(String[] args) { try { URL url = new URL(path); HttpURLConnection conn = (HttpURLConnection) url.openConnection(); conn.setRequestMethod("GET"); conn.setConnectTimeout(5000); int code = conn.getResponseCode(); if (code == 200) { // 获取文件大小 int length = conn.getContentLength(); // 创建一个和服务器获取的文件大小一致的文件 RandomAccessFile randomAccessFile = new RandomAccessFile("lol.exe", "rw"); randomAccessFile.setLength(length); // 算出每个线程下载大小 int blockSize = length / THREADACOUNT; // 计算每个线程的起始位置和结束位置 for (int i = 0; i < THREADACOUNT; i++) { int startIndex = i * blockSize; int endIndex = (i + 1) * blockSize - 1; // 处理最后一个线程结束位置 if (i == THREADACOUNT - 1) { endIndex = length - 1; } // 开启多线程下载 new DowdLoadThread(startIndex, endIndex, i).start(); } } } catch (Exception e) { e.printStackTrace(); } } // 定义多线程下载文件 private static class DowdLoadThread extends Thread { private int startIndex; private int endIndex; private int threadID; public DowdLoadThread(int startIndex, int endIndex, int threadID) { this.startIndex = startIndex; this.endIndex = endIndex; this.threadID = threadID; } @Override public void run() { try { URL url = new URL(path); HttpURLConnection conn = (HttpURLConnection) url.openConnection(); conn.setRequestMethod("GET"); conn.setConnectTimeout(5000); // 设置 conn.setRequestProperty("Range", "bytes=" + startIndex + "-" + endIndex); int code = conn.getResponseCode(); // 请求部分资源成功(206) if (code == 206) { // 随机读写文件对象 RandomAccessFile randomAccessFile = new RandomAccessFile("lol.exe", "rw"); randomAccessFile.seek(startIndex); InputStream in = conn.getInputStream(); // 当前线程下载的大小 int len = -1; byte[] buffer = new byte[1024]; while ((len = in.read(buffer)) != -1) { randomAccessFile.write(buffer, 0, len); } randomAccessFile.close(); System.out.println("线程id:" + threadID + "已下载完毕"); } } catch (Exception e) { e.printStackTrace(); } } } }
执行:
接下来实现断点续传:
package demo; import java.io.BufferedReader; import java.io.File; import java.io.FileInputStream; import java.io.InputStream; import java.io.InputStreamReader; import java.io.RandomAccessFile; import java.net.HttpURLConnection; import java.net.URL; public class MutilDownLoad { // 定义下载的路径 private static String path = "http://192.168.87.1:8080/lol.exe"; // 假设开三个线程 private static final int threadCount = 3; // 代表当前正在运行的线程 private static int runningThread; public static void main(String[] args) { try { URL url = new URL(path); HttpURLConnection conn = (HttpURLConnection) url.openConnection(); conn.setRequestMethod("GET"); conn.setConnectTimeout(5000); int code = conn.getResponseCode(); if (code == 200) { int length = conn.getContentLength(); runningThread = threadCount; System.out.println("length:" + length); RandomAccessFile rafAccessFile = new RandomAccessFile(getFilename(path), "rw"); rafAccessFile.setLength(length); int blockSize = length / threadCount; for (int i = 0; i < threadCount; i++) { int startIndex = i * blockSize; int endIndex = (i + 1) * blockSize - 1; if (i == threadCount - 1) { endIndex = length - 1; } System.out.println("线程id:::" + i + "理论下载的位置" + ":" + startIndex + "-----" + endIndex); DownLoadThread downLoadThread = new DownLoadThread(startIndex, endIndex, i); downLoadThread.start(); } } } catch (Exception e) { e.printStackTrace(); } } private static class DownLoadThread extends Thread { private int startIndex; private int endIndex; private int threadId; public DownLoadThread(int startIndex, int endIndex, int threadId) { this.startIndex = startIndex; this.endIndex = endIndex; this.threadId = threadId; } @Override public void run() { try { URL url = new URL(path); HttpURLConnection conn = (HttpURLConnection) url.openConnection(); conn.setRequestMethod("GET"); conn.setConnectTimeout(5000); File file = new File(getFilename(path) + threadId + ".txt"); if (file.exists() && file.length() > 0) { FileInputStream fis = new FileInputStream(file); BufferedReader bufr = new BufferedReader(new InputStreamReader(fis)); String lastPositionn = bufr.readLine(); int lastPosition = Integer.parseInt(lastPositionn); startIndex = lastPosition + 1; System.out.println("线程id::" + threadId + "真实下载的位置" + ":" + startIndex + "-----" + endIndex); fis.close(); } conn.setRequestProperty("Range", "bytes=" + startIndex + "-" + endIndex); int code = conn.getResponseCode(); if (code == 206) { RandomAccessFile raf = new RandomAccessFile(getFilename(path), "rw"); raf.seek(startIndex); InputStream in = conn.getInputStream(); int len = -1; byte[] buffer = new byte[1024 * 1024];// 1Mb int total = 0; while ((len = in.read(buffer)) != -1) { raf.write(buffer, 0, len); total += len; // 实现断点续传 就是把当前线程下载的位置 给存起来 下次再下载的时候 就是按照上次下载的位置继续下载 // 存到一个普通的.txt文本中 int currentThreadPosition = startIndex + total; RandomAccessFile raff = new RandomAccessFile(getFilename(path) + threadId + ".txt", "rwd"); raff.write(String.valueOf(currentThreadPosition).getBytes()); raff.close(); } raf.close(); System.out.println("线程id:" + threadId + "---下载完毕了"); // 把.txt文件删除 每个线程具体什么时候下载完毕了 我们不知道 // 线程同步锁 synchronized (DownLoadThread.class) { runningThread--; if (runningThread == 0) { // 所有的线程都执行完毕了 就把.txt文件删除 for (int i = 0; i < threadCount; i++) { File delteFile = new File(getFilename(path) + i + ".txt"); delteFile.delete(); } } } } } catch (Exception e) { e.printStackTrace(); } } } // 获取文件的名字 public static String getFilename(String path) { int start = path.lastIndexOf("/") + 1; return path.substring(start); } }