//建立连接 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;
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));
}
}



