package instance25;
import java.io.IOException;
public class MutilDown {
//定义获取指定网络资源长度的方法
public static long getFileLength(URL url) throws IOException{
long length = 0;
URLConnection con = url.openConnection();
//获取连接URL资源的长度
long size = con.getContentLength();
length = size;
return length;
}
public static void main(String[] args) {
final int DOWN_THREAD_NUM = 4;
final String OUT_FILE_NAME = "down.jpg";
InputStream[] isArr = new InputStream[DOWN_THREAD_NUM];
RandomAccessFile[] outArr = new RandomAccessFile[DOWN_THREAD_NUM];
try{
URL url = new URL("http://images.china-pub.com/"+"ebook35001-40000/35850/shupi.jpg");
//以此URL对象打开第一个输入流
isArr[0] = url.openStream();
long fileLen = getFileLength(url);
System.out.println("网络资源的大小:"+fileLen);
//以输出文件名创建第一个RandomAccessFile输出流
outArr[0] = new RandomAccessFile(OUT_FILE_NAME,"rw");
//创建一个与下载资源相同大小的空文件
for(int i = 0;i<fileLen;i++){
outArr[0].write(0);
}
//每个线程应该下载的字节数
long numPerThred = fileLen/DOWN_THREAD_NUM;
//整个下载资源整除后剩下的余数
long left = fileLen % DOWN_THREAD_NUM;
for(int i = 0 ; i < DOWN_THREAD_NUM;i++){
//为每个线程打开一个输入流,一个RandomAccessFile对象
//让每个线程分别负责下载资源的不同部分
if(i != 0){
//以URL打开多个输入流
isArr[i] = url.openStream();
outArr[i] = new RandomAccessFile(OUT_FILE_NAME,"rw");
}
if(i == DOWN_THREAD_NUM -1){//若是最后一个线程,则下载完剩余的部分
new ThreadDown(i*numPerThred,(i+1)*numPerThred+left,isArr[i],outArr[i]).start();
}else{//否则每个线程自己下载自己的
new ThreadDown(i * numPerThred,(i+1)*numPerThred,isArr[i],outArr[i]).start();
}
}
}catch(Exception e){
}
}
}
package instance25;
import java.io.IOException;
/**
* 定义下载从start到end的内容的线程
* @author
*
*/
public class ThreadDown extends Thread{
private final int BUFF_LEN = 32;
private long start ;
private long end ;
/**
* 下载资源对应的输入流
*/
private InputStream is;
/**
* 将下载到的字节输出到raf中
*/
private RandomAccessFile raf;
/**
* 构造器,传入输入流,输出流和下载起始点、结束点
* @param start
* @param end
* @param is
* @param raf
*/
public ThreadDown(long start,long end,InputStream is,RandomAccessFile raf){
System.out.println("输出该线程下载的起始点,开始位置:"+start+"结束位置:"+end);
this.start = start;
this.end = end;
this.is = is;
this.raf = raf;
}
public void run(){
try{
is.skip(start);
raf.seek(start);
//定义读取输入流内容的缓存数组(竹筒)
byte[] buff = new byte[BUFF_LEN];
//定义本线程下载的资源大小
long contentLen = end - start;
long times = contentLen/BUFF_LEN + 4;
int hasRead = 0;
for(int i = 0;i < times; i++){
hasRead = is.read(buff);
//如果读取的字节数小于0,则退出循环
if(hasRead < 0){
break;
}
raf.write(buff,0,hasRead);
}
}catch(Exception e){
e.printStackTrace();
}finally{
if(is != null){
try {
is.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if(raf != null){
try {
raf.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}