'''java
import java.io.*;
import java.net.HttpURLConnection;
import java.net.URL;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.StandardCopyOption;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
public class MultiThreadDownloader {
private final static int BUFFER_SIZE = 4096;
public static void main(String[] args) throws IOException {
String fileUrl = "http://www.example.com/largefile.zip";
Path saveDir = Path.of("downloads");
int numThreads = 4;
long fileSize = getFileSize(fileUrl);
List<DownloadTask> tasks = splitTasks(numThreads, fileSize);
ExecutorService executor = Executors.newFixedThreadPool(numThreads);
List<CompletableFuture<Void>> futures = new ArrayList<>();
for (DownloadTask task : tasks) {
futures.add(CompletableFuture.runAsync(() -> {
try {
downloadChunk(fileUrl, saveDir, task.startPos, task.endPos);
} catch (IOException e) {
e.printStackTrace();
}
}, executor));
}
CompletableFuture.allOf(futures.toArray(new CompletableFuture[0]))
.thenRun(() -> {
System.out.println("Download finished!");
executor.shutdown();
})
.exceptionally(ex -> {
System.err.println("Download failed: " + ex.getMessage());
executor.shutdown();
return null;
});
}
private static void downloadChunk(String fileUrl, Path saveDir, long startPos, long endPos) throws IOException {
HttpURLConnection connection = (HttpURLConnection) new URL(fileUrl).openConnection();
connection.setRequestProperty("Range", "bytes=" + startPos + "-" + endPos);
try (InputStream input = connection.getInputStream();
OutputStream output = new BufferedOutputStream(Files.newOutputStream(saveDir, StandardCopyOption.CREATE, StandardCopyOption.APPEND))) {
byte[] buffer = new byte[BUFFER_SIZE];
int bytesRead;
while ((bytesRead = input.read(buffer)) != -1) {
output.write(buffer, 0, bytesRead);
}
}
}
private static long getFileSize(String fileUrl) throws IOException {
HttpURLConnection connection = (HttpURLConnection) new URL(fileUrl).openConnection();
return connection.getContentLengthLong();
}
private static List<DownloadTask> splitTasks(int numThreads, long fileSize) {
long chunkSize = fileSize / numThreads;
List<DownloadTask> tasks = new ArrayList<>();
for (int i = 0; i < numThreads; i++) {
long startPos = i * chunkSize;
long endPos = (i == numThreads - 1) ? fileSize - 1 : (startPos + chunkSize - 1);
tasks.add(new DownloadTask(startPos, endPos));
}
return tasks;
}
private static class DownloadTask {
private final long startPos;
private final long endPos;
public DownloadTask(long startPos, long endPos) {
this.startPos = startPos;
this.endPos = endPos;
}
}
}
'''