`
zhujianjia
  • 浏览: 477585 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

Java学习 之 多线程下载文件【源码】

 
阅读更多

负责下载的线程:

import java.io.IOException;  
import java.io.InputStream;  
import java.io.RandomAccessFile;  
  
  
public class DownloadThread extends Thread {  
      
    // 定义字节数组(用于取水的那个竹筒)的长度  
    private final int BUFF_LEN = 100;  
    // 定义下载的起始点  
    private long start;  
    // 定义下载的结束点  
    private long end;  
    // 下载资源对应的输入流  
    private InputStream inputStream;  
    // 下载资源对应的输出流  
    private RandomAccessFile randomAccessFile;  
      
    // 构造器:传入起始下载点,结束下载点,输入流,输出流  
    public DownloadThread (long start,long end,InputStream inputStream,RandomAccessFile randomAccessFile) {  
        // 打印一下该线程的起始下载点和结束下载点的位置信息  
        System.out.println(start+" >------> "+end);  
        this.start = start;  
        this.end = end;  
        this.inputStream = inputStream;  
        this.randomAccessFile = randomAccessFile;  
    }  
      
    @Override  
    public void run() {  
        try {  
            // 记录指针向前移动start个字符  
            inputStream.skip(start);  
            // 记录指针定位到start位置处  
            randomAccessFile.seek(start);  
            // 定义读取输入流内容的缓存数组(竹筒)  
            byte[] buff = new byte[BUFF_LEN];  
            // 本线程负责下载的资源大小  
            long contentLen = end - start;  
            // 定义最多需要几次就可以完成本线程的下载任务,方便控制线程的退出  
            long readMaxTimes = contentLen/BUFF_LEN + 4;  
            // 实际读取的字节数  
            int reallyReadCount = 0;  
            for (int i = 0; i < readMaxTimes; i++) {  
                // 读取数据  
                reallyReadCount = inputStream.read(buff);  
                // 如果读取的字节数小于0,说明读取完毕,则退出循环  
                if (reallyReadCount < 0) {  
                    break;  
                }  
                // 写入数据  
                randomAccessFile.write(buff, 0, reallyReadCount);  
            }  
        } catch (IOException e) {  
            e.printStackTrace();  
        } finally {  
            // 使用finally块来关闭当前线程的输入流和输出流      
            try {  
                if (inputStream != null) {  
                    inputStream.close();  
                }  
                if (randomAccessFile != null) {  
                    randomAccessFile.close();  
                }  
            } catch (IOException e) {  
                e.printStackTrace();  
            }  
        }  
    }  
          
}  

 

传入Url地址,开启下载:

import java.io.IOException;  
import java.io.InputStream;  
import java.io.RandomAccessFile;  
import java.net.MalformedURLException;  
import java.net.URL;  
import java.net.URLConnection;  
  
public class MultiDownload {  
      
    public static void main(String[] args) {  
        // 定义开启的线程数  
        final int DOWNLOAD_THREAD_NUM = 4;  
        // 定义下载文件的文件名,包括后缀  
        final String OUTPUT_FILE_NAME = "baidu.gif";  
        // 定义一个DOWNLOAD_THREAD_NUM大小的输入流数组  
        InputStream[] inArrays = new InputStream[DOWNLOAD_THREAD_NUM];  
        // 定义一个DOWNLOAD_THREAD_NUM大小的输出流数组  
        RandomAccessFile[] outArrays = new RandomAccessFile[DOWNLOAD_THREAD_NUM];  
          
        try {  
            // 创建一个URL对象,参数是我们要下载的资源的地址  
            URL downloadUrl = new URL("http://www.baidu.com/img/baidu_sylogo1.gif");  
            // 以该URL对象打开第一个输入流  
            inArrays[0] = downloadUrl.openStream();  
            // 获取该网络资源文件的长度  
            long fileLength = getFileLength(downloadUrl);  
            // 做一个打印  
            System.out.println("该网络资源文件的大小:"+fileLength);  
            // 以输出的文件名创建第一个输出流对象,模式是可读,可写  
            outArrays[0] = new RandomAccessFile(OUTPUT_FILE_NAME, "rw");  
            // 创建一个与下载资源文件相同大小的空文件  
            for (int i = 0; i < fileLength; i++) {  
                outArrays[0].write(0);  
            }  
            // 计算每个线程应该下载的字节数  
            long everyThreadDownloadSize = fileLength/DOWNLOAD_THREAD_NUM;  
            // 计算整个下载资源整除后剩下的余数  
            long otherDownloadSize = fileLength%DOWNLOAD_THREAD_NUM;  
            // 启动各个线程下载各自规定的读取长度的资源  
            for (int i = 0; i < DOWNLOAD_THREAD_NUM; i++) {  
                // 刚才只初始化了第一个输入流和输出流对象,初始化剩下的输入流和输出流对象  
                if (i != 0) {  
                    inArrays[i] = downloadUrl.openStream();  
                    outArrays[i] = new RandomAccessFile(OUTPUT_FILE_NAME, "rw");  
                }  
                // 独立配置最后一个线程的下载参数(该线程负责下载整除后余下的资源)  
                if (i == DOWNLOAD_THREAD_NUM -1) {  
                    new DownloadThread(i*everyThreadDownloadSize, (i+1)*everyThreadDownloadSize+otherDownloadSize, inArrays[i], outArrays[i]);  
                } else {  
                    // 配置前几个线程的下载参数  
                    new DownloadThread(i*everyThreadDownloadSize, (i+1)*everyThreadDownloadSize, inArrays[i], outArrays[i]);  
                }  
            }  
        } catch (MalformedURLException e) {  
            e.printStackTrace();  
        } catch (IOException e) {  
            e.printStackTrace();  
        }  
          
          
    }  
      
    // 根据URL获取该URL所指向的资源文件的长度  
    private static long getFileLength(URL url) throws IOException{  
        long length = 0;  
        URLConnection urlConnection = url.openConnection();  
        long size = urlConnection.getContentLength();  
        length = size;  
        return length;  
    }  
}  

 

转自:http://emmet1988.iteye.com/blog/1065251

分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics