Sorta
zhouyiran2 发表于 2014-1-5 16:27
1.请记住,建立连接是需要时间的,所有多线程的优势在于较大一些的文件上会有一定优势,但在assets资源中 ...

第一种多线程同源多线程

  1.     import java.io.File;   
  2.     import java.io.IOException;   
  3.     import java.io.InputStream;   
  4.     import java.io.RandomAccessFile;   
  5.     import java.net.HttpURLConnection;   
  6.     import java.net.URL;   
  7.     /**  
  8.      * 多线程方式文件下载  
  9.      */   
  10.     public class MulThreadDownload {   
  11.         /* 下载的URL */   
  12.         private URL downloadUrl;   
  13.         /* 用于保存的本地文件 */   
  14.         private File localFile;   
  15.         /* 没条线程下载的数据长度 */   
  16.         private int block;   
  17.         public static void main(String[] args) {   
  18.             /* 可以为网络上任意合法下载地址 */   
  19.             String downPath = "http://192.168.1.102:8080/myvideoweb/down.avi";   
  20.             MulThreadDownload threadDownload = new MulThreadDownload();   
  21.             /* 开 10 条线程下载下载 */   
  22.             try {   
  23.                 threadDownload.download(downPath, 10);   
  24.             } catch (Exception e) {   
  25.                 e.printStackTrace();   
  26.             }   
  27.         }   
  28.         /**  
  29.          * 多线程文件下载  
  30.          *   
  31.          * @param path 下载地址  
  32.          * @param threadCount 线程数  
  33.          */   
  34.         public void download(String path, int threadCount) throws Exception {   
  35.             downloadUrl = new URL(path);   
  36.             HttpURLConnection conn = (HttpURLConnection) downloadUrl   
  37.                     .openConnection();   
  38.             /* 设置 GET 请求方式 */   
  39.             conn.setRequestMethod("GET");   
  40.             /* 设置响应时间超时为 5 秒 */   
  41.             conn.setConnectTimeout(5 * 1000);   
  42.             /* 获取本地文件名 */   
  43.             String filename = parseFilename(path);   
  44.             /* 获取下载文件的总大小 */   
  45.             int dataLen = conn.getContentLength();   
  46.             if (dataLen < 0) {   
  47.                 System.out.println("获取数据失败");   
  48.                 return;   
  49.             }   
  50.             /* 创建本地目标文件,并设置其大小为准备下载文件的总大小 */   
  51.             localFile = new File(filename);   
  52.             RandomAccessFile accessFile = new RandomAccessFile(localFile, "rwd");   
  53.             /* 这时候,其实本地目录下,已经创建好了一个大小为下载文件的总大小的文件 */   
  54.             accessFile.setLength(dataLen);   
  55.             accessFile.close();   
  56.             /* 计算每条线程要下载的数据大小 */   
  57.             block = dataLen % threadCount == 0 ? dataLen / threadCount : dataLen / threadCount + 1;   
  58.             /* 启动线程下载文件 */   
  59.             for (int i = 0; i < threadCount; i++) {   
  60.                 new DownloadThread(i).start();   
  61.             }   
  62.         }   
  63.         /**  
  64.          * 解析文件  
  65.          */   
  66.         private String parseFilename(String path) {   
  67.             return path.substring(path.lastIndexOf("/") + 1);   
  68.         }   
  69.         /**  
  70.          * 内部类: 文件下载线程类  
  71.          */   
  72.         private final class DownloadThread extends Thread {   
  73.             /* 线程 id */   
  74.             private int threadid;   
  75.             /* 开始下载的位置 */   
  76.             private int startPosition;   
  77.             /* 结束下载的位置 */   
  78.             private int endPosition;   
  79.             /**  
  80.              * 新建一个下载线程  
  81.              * @param threadid 线程 id  
  82.              */   
  83.             public DownloadThread(int threadid) {   
  84.                 this.threadid = threadid;   
  85.                 startPosition = threadid * block;   
  86.                 endPosition = (threadid + 1) * block - 1;   
  87.             }   
  88.             @Override   
  89.             public void run() {   
  90.                 System.out.println("线程 '" + threadid + "'启动下载..");   
  91.                     
  92.                 RandomAccessFile accessFile = null;   
  93.                 try {   
  94.                     /* 设置从本地文件的什么位置开始写入数据 ,"rwd" 表示对文件具有读写删权限 */   
  95.                     accessFile = new RandomAccessFile(localFile, "rwd");   
  96.                     accessFile.seek(startPosition);   
  97.                     HttpURLConnection conn = (HttpURLConnection) downloadUrl.openConnection();   
  98.                     conn.setRequestMethod("GET");   
  99.                     conn.setReadTimeout(5 * 1000);   
  100.                     /* 为 HTTP 设置 Range 属性,可以指定服务器返回数据的范围 */   
  101.                     conn.setRequestProperty("Range", "bytes=" + startPosition + "-"   
  102.                             + endPosition);   
  103.                     /* 将数据写往本地文件 */   
  104.                     writeTo(accessFile, conn);   
  105.                         
  106.                     System.out.println("线程 '" + threadid + "'完成下载");   
  107.                 } catch (IOException e) {   
  108.                     e.printStackTrace();   
  109.                 } finally {   
  110.                     try {   
  111.                         if(accessFile != null) {   
  112.                             accessFile.close();   
  113.                         }   
  114.                      } catch (IOException ex) {   
  115.                          ex.printStackTrace();   
  116.                      }   
  117.                 }   
  118.             }   
  119.             /**  
  120.              * 将下载数据写往本地文件  
  121.              */   
  122.             private void writeTo(RandomAccessFile accessFile,   
  123.                     HttpURLConnection conn){   
  124.                 InputStream is = null;   
  125.                 try {   
  126.                     is = conn.getInputStream();   
  127.                     byte[] buffer = new byte[1024];   
  128.                     int len = -1;   
  129.                     while ((len = is.read(buffer)) != -1) {   
  130.                         accessFile.write(buffer, 0, len);   
  131.                     }   
  132.                 } catch (IOException e) {   
  133.                     e.printStackTrace();   
  134.                 } finally {   
  135.                     try {   
  136.                         if(is != null) {   
  137.                             is.close();   
  138.                         }     
  139.                     } catch (Exception ex) {   
  140.                         ex.printStackTrace();   
  141.                     }   
  142.                 }   
  143.             }   
  144.         }   
  145.     }   
复制代码
第二种就不是同源多线程

显而易见的 这两种肯定都比单线程快

但是如果我写这段代码的话 我懒得用多线程

zhouyiran2
Sorta 发表于 2014-1-5 16:49
第一种多线程同源多线程第二种就不是同源多线程

显而易见的 这两种肯定都比单线程快

1.我问你,is = conn.getInputStream();  需要时间么?如果一个文件只有几百B或几K,你说哪个效率高?建立Http连接、创建线程都是要系统资源、时间的!

Sorta
zhouyiran2 发表于 2014-1-5 16:58
1.我问你,is = conn.getInputStream();  需要时间么?如果一个文件只有几百B或几K,你说哪个效率高?建立 ...

请自行尝试

zhouyiran2
Sorta 发表于 2014-1-5 17:00
请自行尝试

你自行尝试过吗?

huanghongxun
表示只是为了省事不想写多线程。

zhh0000zhh
刚看到。。。
感谢你的好意。。
不过我刚才试了一下,多线程下载对于大资源文件加速极为明显,最大可达到理论速度(线程数*单线程速度)
至于小文件从没想过使用多线程。。。

zhouyiran2
zhh0000zhh 发表于 2014-4-26 10:45
刚看到。。。
感谢你的好意。。
不过我刚才试了一下,多线程下载对于大资源文件加速极为明显,最大可达到理 ...

谢谢,那个已经经过了实验,证明速度慢和我的下载器的缺陷有一定关系,准备对WebClient进行改造来避免问题

zhh0000zhh
zhouyiran2 发表于 2014-4-26 11:01
谢谢,那个已经经过了实验,证明速度慢和我的下载器的缺陷有一定关系,准备对WebClient进行改造来避免问 ...

WebClient没有任何前途。。。
用httpresponse自己写吧

zhouyiran2
zhh0000zhh 发表于 2014-4-26 14:25
WebClient没有任何前途。。。
用httpresponse自己写吧

我说的是WebClient的网络部分写得还是可以的,至少效果比我自己写出来的好,准备好好看看到底差别问题出在哪里

zhh0000zhh
zhouyiran2 发表于 2014-4-26 15:23
我说的是WebClient的网络部分写得还是可以的,至少效果比我自己写出来的好,准备好好看看到底差别问题出在 ...

好吧。。。。。

第一页 上一页