使用多线程拆分文件下载

首先我们从任意的一个地方获得资源,考虑到你的带宽创建线程
我们现在创建一个简单的多线程解析资源

public class DownLoadRunable implements Runnable {
private int threadId;
private int startIndex;
private int endIndex;
private String path;

public DownLoadRunable(String path,int threadId, int startIndex, int endIndex) {
super();
this.threadId = threadId;
this.startIndex = startIndex;
this.endIndex = endIndex;
this.path = path;
}

/*
* (non-Javadoc)
*
* @see java.lang.Runnable#run()
*/
@Override
public void run() {
URL url;
try {
url = new URL(path);
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setConnectTimeout(5000);
conn.setRequestMethod("GET");
// 重要:请求服务器下载部分文件 指定文件的位置
conn.setRequestProperty("Range", "bytes=" + startIndex + "-" + endIndex);
// 从服务器请求全部资源返回200 ok如果从服务器请求部分资源 返回 206 ok
int code = conn.getResponseCode();
System.out.println("code:" + code);
InputStream is = conn.getInputStream();// 已经设置了请求的位置,返回的是当前位置对应的文件的输入流
RandomAccessFile raf = new RandomAccessFile("meinv.jpg", "rwd");
// 随机写文件的时候从哪个位置开始写
raf.seek(startIndex);// 定位文件
int len = 0;
byte[] buffer = new byte[1024];
while ((len = is.read(buffer)) != -1) {
raf.write(buffer, 0, len);
}
is.close();
raf.close();
System.out.println("线程:" + threadId + "下载完毕");
} catch (IOException e) {
e.printStackTrace();
}

}

}



/**
* @author Janle
*
*/
public class DowloadDemo {
// 文件路径
public static String[] paths = { "http://img.ugirls.com/uploads/cooperate/baidu/20160408jzx3.jpg",
"http://b.hiphotos.baidu.com/image/h%3D360/sign=a813da3172094b36c4921deb93ce7c00/810a19d8bc3eb135aa449355a21ea8d3fc1f4458.jpg",
"http://a.hiphotos.baidu.com/image/h%3D360/sign=c429bad21dd8bc3ed90800ccb28aa6c8/e7cd7b899e510fb3a78c787fdd33c895d0430c44.jpg" };
// 线程数
public static int threadCount = 3;
private static ExecutorService threads = Executors.newFixedThreadPool(4);

public static void main(String[] args) {
try {
for (String path : paths) {
// 1.连接服务器,获取一个文件,获取文件的长度,在本地创建一个跟服务器一样大小的临时文件
URL url = new URL(path);
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setConnectTimeout(5000);
conn.setRequestMethod("GET");
int code = conn.getResponseCode();// 获得相应的状态码如果是200就说明请求成功
if (code == 200) {
splitTaskToThread(path, conn.getContentLength());
}
}
threads.shutdown();
} catch (IOException e) {
e.printStackTrace();
}
}

/**
* 将资源拆分到线程资源中
*
* @param fileSize
*/
private static void splitTaskToThread(String path, int fileSize) {
// 假设是3个线程去下载资源。
// 平均每一个线程下载的文件大小.
int blockSize = fileSize / threadCount;// 线程执行块的大小
for (int threadId = 1; threadId <= threadCount; threadId++) {
// 线程下载的开始位置
int startIndex = (threadId - 1) * blockSize;// 线程执行开始位置
int endIndex = threadId * blockSize - 1;
if (threadId == threadCount) {// 如果任务分配线程和线程的数量相同的时候直接将最后位置给截止位置【最后一块稍微大点】
endIndex = fileSize;
}
threads.execute(new DownLoadRunable(path, startIndex, endIndex));
}
}
}

class DownLoadRunable implements Runnable {
private int startIndex;
private int endIndex;
private String path;

public DownLoadRunable(String path, int startIndex, int endIndex) {
super();
this.startIndex = startIndex;
this.endIndex = endIndex;
this.path = path;
}

/*
* (non-Javadoc)
*
* @see java.lang.Runnable#run()
*/
@Override
public void run() {
URL url;
try {
url = new URL(path);
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setConnectTimeout(5000);
conn.setRequestMethod("GET");
// 重要:请求服务器下载部分文件 指定文件的位置
conn.setRequestProperty("Range", "bytes=" + startIndex + "-" + endIndex);
// 从服务器请求全部资源返回200 ok如果从服务器请求部分资源 返回 206 ok
int code = conn.getResponseCode();
System.out.println("code:" + code);
InputStream is = conn.getInputStream();// 已经设置了请求的位置,返回的是当前位置对应的文件的输入流
String urlPath = conn.getURL().getFile();
String fileFullName = urlPath.substring(urlPath.lastIndexOf("/") + 1);
RandomAccessFile raf = new RandomAccessFile(fileFullName, "rwd");
// 随机写文件的时候从哪个位置开始写
raf.seek(startIndex);// 定位文件
int len = 0;
byte[] buffer = new byte[1024];
while ((len = is.read(buffer)) != -1) {
raf.write(buffer, 0, len);
}
is.close();
raf.close();
System.out.println("线程:" + Thread.currentThread().getName() + "下载完毕");
} catch (IOException e) {
e.printStackTrace();
}

}

}





多线程分发
(size / nThreads * i, size / nThreads * (i + 1));
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值