//建立连接 url
package com.czb.demo1; import java.io.IOException; import java.net.HttpURLConnection; import java.net.URL; public class Util { // 记录读取了多少,一共读取了多少 public static long start; // 记录文件总大小 public static long sum; /** * * @Title: getHttpConnection * @Description: 获取 url 连接 * @param: @param urlLocation * @param: @return HttpURLConnection实例化对象 * @param: @throws IOException * @return: HttpURLConnection * @throws */ public static HttpURLConnection getHttpConnection(String urlLocation) throws IOException { URL url = new URL(urlLocation); HttpURLConnection conn = (HttpURLConnection) url.openConnection(); conn.setConnectTimeout(5000); conn.setRequestMethod("GET"); return conn; } }
//文件下载
package com.czb.demo1; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; public class DownloadFilePool { //2.文件切片,分别指定 起始点,注意这里的起始点是包头也包尾的,0-10/11-20/21-30 这种 // 网络资源路径 private String urlLocation; // 存储路径 private String filePath; // 多少个线程 private int poolLength; public DownloadFilePool(String urlLocation, String filePath, int poolLength) { super(); //如果 保存路径为空则默认存在 D盘,文件名跟下载名相同 if( filePath==null ) { String fileName = urlLocation.substring( urlLocation.lastIndexOf("/") +1); filePath = "D:/" + fileName; } this.urlLocation = urlLocation; this.filePath = filePath; this.poolLength = poolLength; } public void getFile() { try { // 获取文件长度 long fileLength = Util.getHttpConnection(urlLocation).getContentLengthLong(); //给线程文件总大小赋值 Util.sum = fileLength; //定义线程池newCachedThreadPool //newCachedThreadPool创建一个可缓存线程池,如果线程池长度超过处理需要,可灵活回收空闲线程,若无可回收,则新建线程。 //newFixedThreadPool 创建一个定长线程池,可控制线程最大并发数,超出的线程会在队列中等待。 //newScheduledThreadPool 创建一个定长线程池,支持定时及周期性任务执行。 //newSingleThreadExecutor 创建一个单线程化的线程池,它只会用唯一的工作线程来执行任务,保证所有任务按照指定顺序(FIFO, LIFO, 优先级)执行。 ExecutorService pool = Executors.newCachedThreadPool(); // 获取每片大小 long slice = fileLength/poolLength; for(int i = 0 ;i < poolLength; i++) { long start = i*slice; long end = (i+1)*slice -1; if(i==poolLength-1) { start = i*slice; end = fileLength ; } System.out.println( start + "---" + end ); // 创建下载类 DownloadFileRang downloadFileRang = new DownloadFileRang(start, end, urlLocation, filePath); // 执行线程 pool.execute(downloadFileRang); } // 关闭线程池 pool.shutdown(); } catch (Exception e) { e.printStackTrace(); } } }
//文件读取
package com.czb.demo1; import java.io.File; import java.io.InputStream; import java.io.RandomAccessFile; import java.net.HttpURLConnection; public class DownloadFileRang implements Runnable{ // 文件开始位置 private long start ; // 文件结束位置 private long end; // url地址 private String urlLocation; // 文件存储位置 private String filePath; public DownloadFileRang(long start, long end, String urlLocation, String filePath) { super(); this.start = start; this.end = end; this.urlLocation = urlLocation; this.filePath = filePath; } @Override public void run() { try { // 获取连接 HttpURLConnection conn = Util.getHttpConnection(urlLocation); // 设置获取资源范围 conn.setRequestProperty("Range", "bytes=" + start +"-"+end ); File file = new File(filePath); RandomAccessFile out = null; if(file!=null) { //输出流,开始写数据,随机读写流 //r 以只读的方式打开文本,也就意味着不能用write来操作文件 //rw 读操作和写操作都是允许的 //rws 每当进行写操作,同步的刷新到磁盘,刷新内容和元数据 //rwd 每当进行写操作,同步的刷新到磁盘,刷新内容 out = new RandomAccessFile(file, "rw"); } out.seek(start); // 获取网络连接的 输入流 InputStream is = conn.getInputStream(); // byte数组 byte [] data = new byte[1024]; int len = 0; while( (len = is.read(data))!=-1 ) { out.write(data, 0, len); synchronized (Util.class) { Util.start += len; } } // 关闭连接 out.close(); is.close(); } catch (Exception e) { e.printStackTrace(); } } }//
//测试类
package com.czb.demo1; import java.io.IOException; import java.net.HttpURLConnection; import java.net.MalformedURLException; import java.net.URL; public class DownLoadTest2 { static String path = "http://download2.m3guo.com/MSangoSetup1.2.22.51.exe";//资源地址 static int countThread=8;//线程数 static int okThread=0;//和线程数有关,记录线程完成的个数 public static void main(String[] args) { long start = System.currentTimeMillis(); //统一资源管理器,可以直接打开网络地址 try { //建立链接 URL url = new URL(DownLoadTest2.path); //因为是基于Http请求,获取httpUrlConnection,获取网络连接对象,和服务器联系 HttpURLConnection conn = (HttpURLConnection) url.openConnection(); //设置参数 conn.setRequestMethod("GET"); conn.setConnectTimeout(50000);//连接超时 conn.setReadTimeout(50000);//读取超时 System.out.println(conn.getResponseCode()); if(conn.getResponseCode()==200){//成功 //获取文件总长度 long count = conn.getContentLengthLong(); //每个线程下载的大小 long size = count/countThread; System.out.println(count); System.out.println(size); //开启线程进行下载 for (int i = 0; i < countThread; i++) { long startIndex = size * i;//开始位置 long endIndex = size * (i+1);//结束位置 System.out.println("startIndex"+startIndex); System.out.println("endIndex"+endIndex); DownLoad2 thread = new DownLoad2(startIndex,endIndex,i); thread.start(); } } } catch (MalformedURLException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } long end = System.currentTimeMillis(); System.out.println("主线的时间:"+(end-start)); } }