A thread can be understood as a download channel. One thread is a file download channel. Multiple threads means opening several download channels at the same time. When the server provides download services, the user downloader shares bandwidth. When the priority is the same, the total server will evenly allocate the total download thread. It is not difficult to understand. If you have many threads, the faster you download it.
The popular download software supports multi-threading and supports mid-time pause downloads. When you start again, you will not download from scratch.
The steps to implement the two functions are as follows:
(1) When connecting to the download resource file, first determine the size of the resource file and create a temporary file of the same size locally to store the download data.
(2) Determine the file size required for each thread based on the number of threads
(3) Determine the start and end download location of each thread according to the file size and number of threads downloaded by each thread, and determine the starting and ending download location of each thread according to the file size and number of threads downloaded by each thread.
(4) In order to realize the breakpoint download function, it is necessary to mark the location of the real-time download of each thread to facilitate the progress download at the beginning next time.
Open 3 thread download views (the default download directory is a project under Java):
The overall implementation code is as follows (there is still a lot of room for optimization, so don’t just look at it and it’s done)
import java.io.BufferedReader;import java.io.File;import java.io.FileInputStream;import java.io.InputStreamReader;import java.io.RandomAccessFile;import java.net.HttpURLConnection;import java.net.URL;public class DownloadLoad { // Declare the download path "Red Alert 2" public static final String PATH = "http://soft3.xzstatic.com/2015/10/hsjj2ghgzh.rar"; public static int threadCount = 0;// Declare the number of threads public static void main(String[] args) { try { URL url = new URL(PATH); // Get the connection HttpURLConnection conn = (HttpURLConnection) url.openConnection(); // Define the file name by getting the connection String[] str = PATH.split("/"); String fileName = str[5]; // Get the download file size int fileLength = conn.getContentLength(); System.out.println(fileName); // Create a randomly written file that is consistent with the server size locally RandomAccessFile raf = new RandomAccessFile(fileName, "rwd"); System.out.println(fileLength); // Test raf.setLength(fileLength); // Custom thread count threadCount = 3; // Calculate the size of data downloaded by each thread int blockSize = fileLength / threadCount; // Start thread download for (int threadId = 1; threadId <= threadCount; threadId++) { // Core code, define the download location at which each thread starts and ends is int startPos = (threadId - 1) * blockSize;// The location at which the download starts int endPos = (threadId * blockSize) - 1;// The location at which the download ends (not including the last piece) if (threadCount == threadId) { endPos = fileLength; } new Thread(new DownloadLoadThread(threadId, startPos, endPos, PATH)) .start(); } } catch (Exception e) { e.printStackTrace(); } } // Implement the download thread static class DownloadLoadThread implements Runnable { private int threadId; private int startPos; private int endPos; private String path; public DownloadLoadThread(int threadId, int startPos, int endPos, String path) { super(); this.threadId = threadId; this.startPos = startPos; this.endPos = endPos; this.path = path; } public void run() { try { URL url = new URL(path); String[] str = PATH.split("/"); String fileName = str[5]; HttpURLConnection conn = (HttpURLConnection) url .openConnection(); // Set the method of URL request (refer to the API for details) conn.setRequestMethod("GET"); // Set 500ms as the timeout value conn.setReadTimeout(5000); File file = new File(threadId + ".txt"); if (file.exists() && file.length() > 0) { BufferedReader br = new BufferedReader( new InputStreamReader(new FileInputStream(file))); String saveStartPos = br.readLine(); if (saveStartPos != null && saveStartPos.length() > 0) { startPos = Integer.parseInt(saveStartPos); } } // Pay attention to the format in double quotes, and cannot contain spaces (such as other characters), otherwise 416 is reported. conn.setRequestProperty("Range", "bytes=" + startPos + "-" + endPos); RandomAccessFile raf = new RandomAccessFile(fileName, "rwd");// Storing the random write file to the download file raf.seek(startPos);// Set the location to start download System.out.println("Thread" + threadId + ":" + startPos + "~~" + endPos); InputStream is = conn.getInputStream(); byte[] b = new byte[1024 * 1024 * 10]; int len = -1; int newPos = startPos; while ((len = is.read(b)) != -1) { RandomAccessFile rr = new RandomAccessFile(file, "rwd");// The file storing the download tag raf.write(b, 0, len); // Save the download tag to the specified document String savaPoint = String.valueOf(newPos += len); rr.write(savaPoint.getBytes()); rr.close(); } is.close(); raf.close(); System.out.println("Download Complete"); } catch (Exception e) { e.printStackTrace(); } } }}Notes:
(1) Understand the calculation method of the start and end positions of each thread download (not including the last thread, start from 0)
Start position = (number of threads - 1) * The length (size) of the file to be downloaded by each thread
End position = (number of threads * file size downloaded by each thread) -1
(2) The download start position assigned by the last thread is the end position of the previous thread, and the end position is the file length.
Therefore, the file length downloaded by the last thread will generally not be the same as the previous thread
(3) The download path of this demonstration is the directory where the Java project is located by default, and the directory cannot contain files with the same name as the downloaded file, otherwise the program will report a 416 network request error.
(4) A mistake I made in implementation conn.setRequestProperty("Range","bytes="+ startPos+"-"+endPos); Be sure to note that the quotes do not necessarily have extra spaces and other characters. I just have a space in the quotes, but the error positioning has always been an inputStream error, and it is very painful to find the wrong ones.
The above is all the content of this article. I hope it will be helpful to everyone's learning and I hope everyone will support Wulin.com more.