了解了这么多与线程相关的知识,那么我们也要实战一下了(在学习本篇知识之前,如果对java中的网络基础链接不太熟悉的,建议先去学一下java网络编程,再来看本文章。)
因为本篇是多线程下载的demo,所以就直接附上代码,里面都写好了注释,不影响对本篇的学习。
package com.liuqiang.Thread; import java.io.InputStream; import java.io.RandomAccessFile; import java.net.HttpURLConnection; import java.net.MalformedURLException; import java.net.URL; public class DownloadFileThread { /** * 多线程下载文件 * * @param args */ // 定义开启线程总数 为3个线程 private static final int threadCount = 3; // 下载文件的url地址 private static final String urlFile = "http://10.135.110.63:8080/BaiduYunGuanjia.exe"; public static void main(String[] args) { new Thread() { public void run() { try { URL url = new URL(urlFile); HttpURLConnection connection = (HttpURLConnection) url.openConnection(); connection.setRequestMethod("GET"); connection.setConnectTimeout(5000); int code = connection.getResponseCode(); if (code == 200) { //(1) 获取文件总大小 int fileLength = connection.getContentLength(); System.out.println("文件总大小" + fileLength); /** * (2) * RandomAccessFile(适用于多线程下载与上传)随机读写文件对象 * 在客户端创建一个与服务器端一模一样大小的文件 * 参数一:文件名 * 参数二:可读可写 */ RandomAccessFile raf = new RandomAccessFile("BaiduYunGuanjia.exe", "rw"); raf.setLength(fileLength); //(3)计算每个线程下载的开始位置与结束位置 int blockSize = fileLength / threadCount; //每个线程下载(平均)的大小 for (int i = 0; i < threadCount; i++) { int startIndex = i * blockSize; //每个线程下载的开始位置 int endIndex = (i + 1) * blockSize - 1; //每个线程下载的结束位置 //特殊情况 最后一个线程(最后一个线程可能会下载多一些) if (i == threadCount - 1) { //说明是最后一个线程 endIndex = fileLength - 1; } //(4)开启线程下载文件 DownloadThered downloadThered = new DownloadThered(startIndex, endIndex, i); downloadThered.start(); } } } catch (Exception e) { e.printStackTrace(); } } ; }.start(); } /** * 开启多线程 下载 * * @author Administrator */ public static class DownloadThered extends Thread { private int startIndex; private int endIndex; private int threadCount; public DownloadThered(int startIndex, int endIndex, int threadCount) { super(); this.startIndex = startIndex; this.endIndex = endIndex; this.threadCount = threadCount; } @Override public void run() { try { URL url = new URL(urlFile); HttpURLConnection connection = (HttpURLConnection) url.openConnection(); connection.setRequestMethod("GET"); connection.setConnectTimeout(5000); //设置请求头 告诉服务器每个线程下载的开始位置与结束位置 connection.setRequestProperty("Range", "bytes=" + startIndex + "-" + endIndex); int code = connection.getResponseCode(); //200代表请求全部资源 206代表请求部分资源 if (code == 206) { /** * RandomAccessFile(适用于多线程下载与上传)随机读写文件对象 * 在客户端创建一个与服务器端一模一样大小的文件 * 参数一:文件名 * 参数二:可读可写 */ RandomAccessFile raf = new RandomAccessFile("BaiduYunGuanjia.exe", "rw"); //定位 也就是设置每个线程从文件的哪个位置开始下载(设置每个线程下载的起始位置) raf.seek(startIndex); InputStream inStream = connection.getInputStream(); //网络获取的数据 //把数据写到文件当中 int len = -1; byte[] buffer = new byte[1024]; while ((len = inStream.read(buffer)) != -1) { raf.write(buffer, 0, len); } raf.close(); System.out.println("线程" + threadCount + "下载完成了"); } } catch (Exception e) { e.printStackTrace(); } } } }
下一篇 线程池详解