Several key steps of multi-threaded breakpoint continuous download:
1. Create temporary file space and calculate the size of each thread that needs to be downloaded
2. startIndex and endIndexe are required for each thread to download. Using the length of the obtained stream divided by size, the size of each thread is obtained, but if the endless amount is left to the last thread to download.
3. Guarantee the mechanism of breakpoint continuation, using temporary files to store the download progress of each thread. Before each download begins, judge whether the temporary file exists and the corresponding thread download record. Start the download according to the record, judge whether each thread has finished downloading, and delete the temporary files through a loop if all the downloads are completed, in order to avoid and Delete temporary files should be locked in the send operation.
4. Specific download process, get the connection again, get the read stream according to the status code of 206, and then Java In the process of io reading and writing, Random Access File is needed to create and write temporary files. Simply speaking, because the parts requested by each thread are different, the time of writing is not written from scratch. Random Access File's seek method supports the location of writing time, that is, the location of writing time. Write the file in the specified location, and then put together several parts to complete the file to download.
5. In addition, there are some details that need to be noticed, such as requesting the code of the network to be implemented in the sub-thread, that is, the code of the specific download process part.
The following is the specific implementation code, which contains detailed annotations:
package com.nocol.mutildownload; 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; /** * @author lxp * * @TODO * */ public class MutilDownLoad { //Get the file download path public static String path = "http://192.168.56.1:8080/haozip.exe"; // Define the number of threads public static int ThreadCount = 3; // === Define running threads=== public static int RunningThread; public static void main(String[] args) throws Exception { // Connect to the server to get the length of the downloaded file // Create URL objects URL url = new URL(path); // Get the connection object HttpURLConnection conn = (HttpURLConnection) url.openConnection(); // Setting the way to request data conn.setRequestMethod("GET"); // Set request timeout conn.setReadTimeout(5000); // Get the server status code int code = conn.getResponseCode(); if (code == 200) { // Get the actual length of the file int lenth = conn.getContentLength(); // === Assign the number of threads to the running thread==== RunningThread = ThreadCount; // Create a file space to download files RandomAccessFile raf = new RandomAccessFile(getName(path), "rw"); // Specify the length of the space (the same length as the file to download) raf.setLength(lenth); raf.close(); // Set the file length for each thread to download int blockSize = lenth / ThreadCount; for (int ThreadId = 1; ThreadId <= ThreadCount; ThreadId++) { // Set the start location of downloads without each thread int startIndex = (ThreadId - 1) * blockSize; int endIndex = startIndex + (blockSize - 1); if (ThreadId == ThreadCount) { endIndex = lenth; } System.out.println(ThreadId + "Size of theoretical download:" + startIndex + "-----" + endIndex); // Open Thread Download DownLoadThread downLoadThread=new DownLoadThread(startIndex, endIndex, ThreadId); downLoadThread.start(); } } } // Create Thread Download Files public static class DownLoadThread extends Thread {//Static inner class private int startIndex; private int endIndex; private int ThreadId; public DownLoadThread(int startIndex, int endIndex, int ThreadId) { this.endIndex = endIndex; this.startIndex = startIndex; this.ThreadId = ThreadId; } @Override public void run() { try { // Create URL objects URL url = new URL(path); // Get the connection object HttpURLConnection conn = (HttpURLConnection) url.openConnection(); // Setting the way to request data conn.setRequestMethod("GET"); // Set request timeout conn.setReadTimeout(5000); // == Encapsulate files that record thread locations into File objects File file = new File(ThreadId + ".txt"); // == Determine whether there is a file that saves the download location of the thread before downloading to determine whether to continue to upload breakpoints if (file.exists()) { FileInputStream fis = new FileInputStream(file); BufferedReader br = new BufferedReader(new InputStreamReader(fis)); // Get the last location of the thread Download String Lastpostion = br.readLine(); // Change to int type int LastPositionn = Integer.parseInt(Lastpostion); // Assign the position to the starting position startIndex = LastPositionn; // Release resources fis.close(); System.out.println(ThreadId + "The actual download size:" + startIndex + "-----" + endIndex); } // Important: Request server download part of the file specified location (request header information) conn.setRequestProperty("Range", "bytes=" + startIndex + "-" + endIndex); // Get the server status code int code = conn.getResponseCode(); if (code == 206) {// The status code = 206 indicates the success of the request for part of the resource // Get the input stream object InputStream in = conn.getInputStream(); // Creating Random Access File Objects RandomAccessFile raf = new RandomAccessFile(MutilDownLoad.getName(path), "rw"); // Specify the start location of the thread download file raf.seek(startIndex); // Write the read file to the created file space int len = 0; byte[] bys = new byte[1024 * 1024]; // === Define the size of the current thread Download int total = 0; while ((len = in.read(bys)) != -1) { raf.write(bys, 0, len); // == Tot is the size of the file that each thread downloads from its actual location. total += len; // == To achieve breakpoint continuation, get the location of the current thread Download int CurrentThreadPosition = startIndex + total; // == Record the download location of the current thread (. txt file), define random access and file object // == "rwd" opens for reading and writing, and for "rw", every update to the file content is synchronously written to the underlying storage device. RandomAccessFile raff = new RandomAccessFile(ThreadId + ".txt", "rwd"); raff.write(String.valueOf(CurrentThreadPosition).getBytes()); raff.close(); } // Release resources in.close(); raf.close(); System.out.println("thread" + ThreadId + "Download completed!"); // === After each thread downloads, delete the'.txt'file of each thread, and lock the deletion operation in order to avoid concurrent operation.==== synchronized (DownLoadThread.class) { RunningThread--;// Threads will not run after downloading, and the number of threads running will be reduced accordingly. if (RunningThread == 0) {// When the number of Running Threads is 0, all the files are downloaded. for (int i = 1; i <= ThreadCount; i++) { File deleteFile = new File(i + ".txt"); deleteFile.delete(); } } } } } catch (Exception e) { e.printStackTrace(); } } } //Get the file name of the source file public static String getName(String path){ //http://192.168.56.1:8080/haozip.exe //Get the index of the last occurrence of "/" int index=path.lastIndexOf("/"); String name=path.substring(index+1); return name; } }