JAVA 多线程下载

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();
        }
      }
    }
  }
 
 
 
}
 

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值