多线程下载网络资源

多线程下载就是把网络上的资源文件划分成多块,然后把每一块分别分给一个线程去下载,下载也就是用InputStream读取资源,然后用RandomAccessFile来实现保存到本地。

由于需要请求网络资源,本地断网所以在本机测试用Tomcat,在eclipse创建一个工程t2,启动服务器,然后去下载b.mp3:

测试类:

package t2;

public class DownloadTest {
    public static void main(String[] args) {
        DownloadTool.resourceDownload("http://localhost:8080/t2/raw/b.mp3");
    }
}

下载工具类:

package t2;

import java.io.IOException;
import java.io.RandomAccessFile;
import java.net.*;

public class DownloadTool {
    public static void resourceDownload(String path) {
        try {
            int startPosition = 0;//记录写入文件时的起始位置
            int threadCount = 4;//线程数量
        
            URL url = new URL(path);
            HttpURLConnection conn = (HttpURLConnection) url.openConnection();//打开连接
            conn.setRequestMethod("GET");//设置为get请求
            conn.setConnectTimeout(6*1000);
            conn.setRequestProperty("range", "bytes="+startPosition+"-");
            
            int fileSize = conn.getContentLength();//获取网络资源的大小
            int block = fileSize/threadCount+1;//计算每个线程所读取的块的大小
            String filename = path.substring(path.lastIndexOf("/")+1);//获取网络资源的文件名
//            System.out.println(filename);
//            System.out.println("fileSize= "+fileSize);
            RandomAccessFile ras = new RandomAccessFile("f:/download/"+filename, "rw");//新建文件,保存在本地
            ras.setLength(fileSize);//设置新建文件的大小
            ras.close();
            //创建4个线程来下载网络资源
            for(int i=0;i<threadCount;i++) {
                //保存每一个线程下载的block到file
                RandomAccessFile file = new RandomAccessFile("f:/download/"+filename,"rw");
                startPosition = i*block;//计算写入文件的起始位置
                file.seek(startPosition);//把文件指针已到起始位置
                System.out.println("the num "+i+" thread started");
                new DownloadThread(i,block,url,file).start();//启动线程
            }
            conn.disconnect();
        } catch (MalformedURLException e) {
            e.printStackTrace();
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } 
    }
}

下载线程类:

package t2;

import java.io.*;
import java.net.*;

public class DownloadThread extends Thread{
    private int i;
    private int block;
    private URL url;
    private RandomAccessFile file;
    
    public DownloadThread(int i,int block,URL url,RandomAccessFile file) {
        this.i = i;
        this.block = block;
        this.url = url;
        this.file = file;
    }
    
    @Override 
    public void run() {
        try {
            HttpURLConnection conn = (HttpURLConnection) url.openConnection();//打开连接
            conn.setReadTimeout(6*1000);
            conn.setRequestMethod("GET");
            InputStream is = conn.getInputStream();//从连接获取InputStream
            byte[] buf = new byte[1024];//读取的缓冲区
            int readSize = 0;//记录线程所读的块大小
            int len = 0;
            System.out.println("bloack"+i+"= "+block);
            
            while((len=is.read(buf))>0 && readSize<block) {//线程下载文件结束的条件之一是readSize<block
                file.write(buf, 0, len);
                readSize += len;
            }
            System.out.println("the num " + i +" thread finished download");
            file.close();
            is.close();
            conn.disconnect();
            
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}
原文地址:https://www.cnblogs.com/UUUP/p/4521717.html