java手机下载功能实现原理,Android学习札记-java实现多线程下载器,30_多线程下载原理介绍和使用...

本文介绍了Java如何利用多线程技术加速文件下载,通过HttpURLConnection管理线程范围,解释了多线程下载原理,如并发优势和服务器资源抢占。实例代码展示了如何使用3个线程下载文件,并提供两种下载实现方法供参考。
摘要由CSDN通过智能技术生成

Android学习笔记---java实现多线程下载器,30_多线程下载原理介绍和使用

2013-04-01

30_多线程下载原理

--------------------

a.文件下载原里:

使用http协议实现多线程下载

b.采用多线程下载,可以抢占服务器cpu的处理时间,实现快速下载

c.使用多线程下载文件可以更快完成文件的下载,多线程下载文件之所以快,是因为其抢占的服务器资

源多。如:假设服务器同时最多服务100个用户,在服务器中一条线程对应一个用户,100条线程在计

算机中并非并发执行,而是由CPU划分时间片轮流执行,如果A应用使用了99条线程下载文件,那么相

当于占用了99个用户的资源,假设一秒内CPU分配给每条线程的平均执行时间是10ms,A应用在服务器

中一秒内就得到了990ms的执行时间,而其他应用在一秒内只有10ms的执行时间。就如同一个水龙头

,每秒出水量相等的情况下,放990毫秒的水

肯定比放10毫秒的水要多。

d.多线程下载的实现过程:

1>首先得到下载文件的长度,然后设置本地文件的长度。

HttpURLConnection.getContentLength();

RandomAccessFile file = new RandomAccessFile("QQWubiSetup.exe","rwd");

file.setLength(filesize);//设置本地文件的长度

2>根据文件长度和线程数计算每条线程下载的数据长度和下载位置。如:文件的长度为6M,线程数为

3,那么,每条线程下载的数据长度为2M,每条线程开始下载的位置如上图所示。

3>使用Http的Range头字段指定每条线程从文件的什么位置开始下载,下载到什么位置为止,如:指

定从文件的2M位置开始下载,下载到位置(4M-1byte)为止,代码如下:

HttpURLConnection.setRequestProperty("Range", "bytes=2097152-4194303");

4>保存文件,使用RandomAccessFile类指定每条线程从本地文件的什么位置开始写入数据。

RandomAccessFile threadfile = new RandomAccessFile("QQWubiSetup.exe ","rwd");

threadfile.seek(2097152);//从文件的什么位置开始写入数据

----------------------------------------------

下面是用java项目实现多线程下载的所有代码:

a.新建DownloadTest的javaProject

/DownloadTest/src/com/credream/download/MulThreadDownLoad.java

package com.credream.download;

import java.io.File;

import java.io.FileNotFoundException;

import java.io.InputStream;

import java.io.RandomAccessFile;

import java.net.HttpURLConnection;

import java.net.URL;

public class MulThreadDownLoad

{

public static void main(String[] args) throws Exception

{

String path="http://192.168.0.110:6118/HttpFileUploadTest/test.zip";

new MulThreadDownLoad().download(path, 3);//调用下载方法,使用3个线程下载

}

/**

* 下载文件的方法

* @param path

* @param threadsize

* @throws Exception

*/

private void download(String path ,int threadsize)throws Exception

{

URL url=new URL(path);

HttpURLConnection conn=

(HttpURLConnection) url.openConnection();

conn.setConnectTimeout(5000);

conn.setRequestMethod("GET");

if(conn.getResponseCode()==200){

int length=conn.getContentLength();

File file=new File(getFileName(path));//如果不给路径的话,那么默认的保存在

//本项目的目录底下

RandomAccessFile accessFile=new RandomAccessFile(file, "rwd");

accessFile.setLength(length);

accessFile.close();

//注意:r以只读方式打开,rw:打开以便于读取和写入

/*rws:s代表的是文件的元数据,就是指的是文件的大小了等等,当设置为rws的时

当文件变化的时候,会自动的把文件的内容和元数据同步到手机的设备上

rwd:表示当文件变化的时候会自动的把文件的内容同步到手机设备上,而不是把文

件的元数据也

同步到手机设备上.

为了避免当手机掉电的时候,会丢失数据,那么最好采用rwd,每写一些数据就立即

同步到手机设备上

不至于数据的损坏

rw的时候,当没有这个文件的时候会创建这个文件.

*/

int block=length%threadsize==0? length/threadsize:length/threadsize+1;

for(int threadid=0;threadid

new DownloadThread(threadid,block,url,file).start();

}

}else {

System.out.println("下载失败!!!");

}

}

//创建线程类

private class DownloadThread extends Thread{

private int threadid;

private int block;

private URL url;

private File file;

public DownloadThread(int threadid, int block, URL url, File file)

{

this.threadid = threadid;

this.block = block;

this.url = url;

this.file = file;

}

@Override

public void run()

{

int start=threadid*block;//计算该线程从网络文件的什么位置开始下载

int end=(threadid+1)*block-1;//下载到网络文件的什么位置结束

RandomAccessFile accessFile;

try

{

accessFile = new RandomAccessFile(file, "rwd");

accessFile.seek(start);

HttpURLConnection conn=(HttpURLConnection) url.openConnection();

conn.setConnectTimeout(5000);

conn.setRequestMethod("GET");

conn.setRequestProperty("Range", "bytes="+start+"-"+end);

//指定下载的区域是个范围byte=0-1000

//注意这里的conn.getResponseCode()==200应该是206,206才对,不然会报错

//if(conn.getResponseCode()==200){

InputStream inpuStream=conn.getInputStream();

byte[] buffer=new byte[1024];

int len=0;

while((len=inpuStream.read(buffer))!=-1){

accessFile.write(buffer,0,len);

}

accessFile.close();

inpuStream.close();

//}

System.out.println("第"+(threadid+1)+"线程已经下载完了");

} catch (Exception e)

{

e.printStackTrace();

}

}

}

//得到要创建的文件名,根据路径

private String getFileName(String path)

{

return path.substring(path.lastIndexOf("/")+1);

}

}

------------------------------------------

2.下面这个是别人提供的,也可以实现下载,原理差不多

/DownloadTest/src/com/credream/downloadFile/FileDownLoader.java

package com.credream.downloadFile;

import java.io.InputStream;

import java.io.RandomAccessFile;

import java.net.HttpURLConnection;

import java.net.URL;

import org.junit.Test;

public class FileDownLoader {

@Test

public void download() throws Exception {

String path = "http://localhost:6118/HttpFileUploadTest/test.zip";

URL url = new URL(path);

HttpURLConnection conn = (HttpURLConnection) url.openConnection();

conn.setConnectTimeout(5*1000);

conn.setRequestMethod("GET");

conn.setRequestProperty("Accept", "image/gif, image/jpeg,

image/pjpeg, image/pjpeg, application/x-shockwave-flash, application/xaml+xml,

application/vnd.ms-xpsdocument, application/x-ms-xbap, application/x-ms-application,

application/vnd.ms-excel, application/vnd.ms-powerpoint, application/msword, */*");

conn.setRequestProperty("Accept-Language", "zh-CN");

conn.setRequestProperty("Charset", "UTF-8");

conn.setRequestProperty("User-Agent", "Mozilla/4.0 (compatible;

MSIE 8.0; Windows NT 5.2; Trident/4.0; .NET CLR 1.1.4322; .NET CLR 2.0.50727; .NET CLR

3.0.04506.30; .NET CLR 3.0.4506.2152; .NET CLR 3.5.30729)");

conn.setRequestProperty("Connection", "Keep-Alive");

System.out.println(conn.getResponseCode());

int filesize = conn.getContentLength();//得到文件大小

conn.disconnect();

int threasize = 3;//线程数

int perthreadsize = filesize / 3 + 1;

RandomAccessFile file = new RandomAccessFile("102.wma","rw");

file.setLength(filesize);//设置本地文件的大小

file.close();

for(int i=0; i

int startpos = i * perthreadsize;//计算每条线程的下载位置

RandomAccessFile perthreadfile = new RandomAccessFile

("102.wma","rw");//

perthreadfile.seek(startpos);//从文件的什么位置开始写入数

new DownladerThread(i, path, startpos, perthreadsize,

perthreadfile).start();

}

//以下代码要求用户输入q才会退出测试方法,如果没有下面代码,会因为

进程结束而导致进程内的下载线程被销毁

int quit = System.in.read();

while('q'!=quit){

Thread.sleep(2 * 1000);

}

}

private class DownladerThread extends Thread{

private int startpos;//从文件的什么位置开始下载

private int perthreadsize;//每条线程需要下载的文件大小

private String path;

private RandomAccessFile file;

private int threadid;

public DownladerThread(int threadid, String path, int startpos,

int perthreadsize, RandomAccessFile perthreadfile) {

this.path = path;

this.startpos = startpos;

this.perthreadsize = perthreadsize;

this.file = perthreadfile;

this.threadid = threadid;

}

@Override

public void run() {

try {

URL url = new URL(path);

HttpURLConnection conn = (HttpURLConnection)

url.openConnection();

conn.setConnectTimeout(5 * 1000);

conn.setRequestMethod("GET");

conn.setRequestProperty("Accept", "image/gif, image/jpeg,

image/pjpeg, image/pjpeg, application/x-shockwave-flash, application/xaml+xml,

application/vnd.ms-xpsdocument, application/x-ms-xbap, application/x-ms-application,

application/vnd.ms-excel, application/vnd.ms-powerpoint, application/msword, */*");

conn.setRequestProperty("Accept-Language", "zh-CN");

conn.setRequestProperty("Charset", "UTF-8");

conn.setRequestProperty("Range", "bytes=" + this.startpos

+ "-");

InputStream inStream = conn.getInputStream();

byte[] buffer = new byte[1024];

int len = 0;

int length = 0;

while(length

(buffer))!=-1){

file.write(buffer, 0, len);

length += len;//累计该线程下载的总大小

}

file.close();

inStream.close();

System.out.println(threadid+ "线程完成下载");

} catch (Exception e) {

e.printStackTrace();

}

}

}

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值