第一种多线程同源多线程
- import java.io.File;
- import java.io.IOException;
- import java.io.InputStream;
- import java.io.RandomAccessFile;
- import java.net.HttpURLConnection;
- import java.net.URL;
- /**
- * 多线程方式文件下载
- */
- public class MulThreadDownload {
- /* 下载的URL */
- private URL downloadUrl;
- /* 用于保存的本地文件 */
- private File localFile;
- /* 没条线程下载的数据长度 */
- private int block;
- public static void main(String[] args) {
- /* 可以为网络上任意合法下载地址 */
- String downPath = "http://192.168.1.102:8080/myvideoweb/down.avi";
- MulThreadDownload threadDownload = new MulThreadDownload();
- /* 开 10 条线程下载下载 */
- try {
- threadDownload.download(downPath, 10);
- } catch (Exception e) {
- e.printStackTrace();
- }
- }
- /**
- * 多线程文件下载
- *
- * @param path 下载地址
- * @param threadCount 线程数
- */
- public void download(String path, int threadCount) throws Exception {
- downloadUrl = new URL(path);
- HttpURLConnection conn = (HttpURLConnection) downloadUrl
- .openConnection();
- /* 设置 GET 请求方式 */
- conn.setRequestMethod("GET");
- /* 设置响应时间超时为 5 秒 */
- conn.setConnectTimeout(5 * 1000);
- /* 获取本地文件名 */
- String filename = parseFilename(path);
- /* 获取下载文件的总大小 */
- int dataLen = conn.getContentLength();
- if (dataLen < 0) {
- System.out.println("获取数据失败");
- return;
- }
- /* 创建本地目标文件,并设置其大小为准备下载文件的总大小 */
- localFile = new File(filename);
- RandomAccessFile accessFile = new RandomAccessFile(localFile, "rwd");
- /* 这时候,其实本地目录下,已经创建好了一个大小为下载文件的总大小的文件 */
- accessFile.setLength(dataLen);
- accessFile.close();
- /* 计算每条线程要下载的数据大小 */
- block = dataLen % threadCount == 0 ? dataLen / threadCount : dataLen / threadCount + 1;
- /* 启动线程下载文件 */
- for (int i = 0; i < threadCount; i++) {
- new DownloadThread(i).start();
- }
- }
- /**
- * 解析文件
- */
- private String parseFilename(String path) {
- return path.substring(path.lastIndexOf("/") + 1);
- }
- /**
- * 内部类: 文件下载线程类
- */
- private final class DownloadThread extends Thread {
- /* 线程 id */
- private int threadid;
- /* 开始下载的位置 */
- private int startPosition;
- /* 结束下载的位置 */
- private int endPosition;
- /**
- * 新建一个下载线程
- * @param threadid 线程 id
- */
- public DownloadThread(int threadid) {
- this.threadid = threadid;
- startPosition = threadid * block;
- endPosition = (threadid + 1) * block - 1;
- }
- @Override
- public void run() {
- System.out.println("线程 '" + threadid + "'启动下载..");
-
- RandomAccessFile accessFile = null;
- try {
- /* 设置从本地文件的什么位置开始写入数据 ,"rwd" 表示对文件具有读写删权限 */
- accessFile = new RandomAccessFile(localFile, "rwd");
- accessFile.seek(startPosition);
- HttpURLConnection conn = (HttpURLConnection) downloadUrl.openConnection();
- conn.setRequestMethod("GET");
- conn.setReadTimeout(5 * 1000);
- /* 为 HTTP 设置 Range 属性,可以指定服务器返回数据的范围 */
- conn.setRequestProperty("Range", "bytes=" + startPosition + "-"
- + endPosition);
- /* 将数据写往本地文件 */
- writeTo(accessFile, conn);
-
- System.out.println("线程 '" + threadid + "'完成下载");
- } catch (IOException e) {
- e.printStackTrace();
- } finally {
- try {
- if(accessFile != null) {
- accessFile.close();
- }
- } catch (IOException ex) {
- ex.printStackTrace();
- }
- }
- }
- /**
- * 将下载数据写往本地文件
- */
- private void writeTo(RandomAccessFile accessFile,
- HttpURLConnection conn){
- InputStream is = null;
- try {
- is = conn.getInputStream();
- byte[] buffer = new byte[1024];
- int len = -1;
- while ((len = is.read(buffer)) != -1) {
- accessFile.write(buffer, 0, len);
- }
- } catch (IOException e) {
- e.printStackTrace();
- } finally {
- try {
- if(is != null) {
- is.close();
- }
- } catch (Exception ex) {
- ex.printStackTrace();
- }
- }
- }
- }
- }
显而易见的 这两种肯定都比单线程快
但是如果我写这段代码的话 我懒得用多线程
1.我问你,is = conn.getInputStream(); 需要时间么?如果一个文件只有几百B或几K,你说哪个效率高?建立Http连接、创建线程都是要系统资源、时间的!
请自行尝试
表示只是为了省事不想写多线程。
刚看到。。。
感谢你的好意。。
不过我刚才试了一下,多线程下载对于大资源文件加速极为明显,最大可达到理论速度(线程数*单线程速度)
至于小文件从没想过使用多线程。。。
感谢你的好意。。
不过我刚才试了一下,多线程下载对于大资源文件加速极为明显,最大可达到理论速度(线程数*单线程速度)
至于小文件从没想过使用多线程。。。
zhh0000zhh 发表于 2014-4-26 10:45
刚看到。。。
感谢你的好意。。
不过我刚才试了一下,多线程下载对于大资源文件加速极为明显,最大可达到理 ...
谢谢,那个已经经过了实验,证明速度慢和我的下载器的缺陷有一定关系,准备对WebClient进行改造来避免问题
zhouyiran2 发表于 2014-4-26 11:01
谢谢,那个已经经过了实验,证明速度慢和我的下载器的缺陷有一定关系,准备对WebClient进行改造来避免问 ...
WebClient没有任何前途。。。
用httpresponse自己写吧
zhh0000zhh 发表于 2014-4-26 14:25
WebClient没有任何前途。。。
用httpresponse自己写吧
我说的是WebClient的网络部分写得还是可以的,至少效果比我自己写出来的好,准备好好看看到底差别问题出在哪里
zhouyiran2 发表于 2014-4-26 15:23
我说的是WebClient的网络部分写得还是可以的,至少效果比我自己写出来的好,准备好好看看到底差别问题出在 ...
好吧。。。。。
