Java 多线程下载示例


项目结构:

FileDownload.java:

package com.wl.download;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.RandomAccessFile;
import java.text.DecimalFormat;

import org.apache.http.HttpResponse;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;

import com.wl.util.DownLoadThread;
import com.wl.util.HttpClientFactory;

public class FileDownload {

	public static void main(String[] args) {
		long startTime = System.currentTimeMillis();
		System.out.println(startTime);

		String srcFileUrl = "http://172.16.2.40:80/2014/12/gpfqpfvlwsvka2mj39pn.mprx";
		String destFilePath = "G:/download/destfile.mprx";
		//获取文件的大小
		long fileSize = getRemoteFileSize(srcFileUrl);

		/**
		 * 每个线程需要下载的文件大小   (自行调整)
		 */
		//long unitSize = 1024 ; //多线程太多 卡死你电脑没问题 

		long unitSize = 1024 * 1024 * 2;  //下载文件大小为  = 535.66M; 23559 millisecond

		//long unitSize = 1024 * 1024 * 50;  //下载文件大小为  = 535.66M; 35726 millisecond

		//long unitSize = fileSize;  //下载文件大小为  = 535.66M;  所使用时间  = 52865 millisecond

		//创建目的文件,并指定大小
		createFile(destFilePath, fileSize);
		//开几个线程去下载
		long threadCount = fileSize / unitSize;
		//写入文件的位置
		long offset = 0;

		if (fileSize <= unitSize) {
			// 如果远程文件尺寸小于等于unitSize
			DownLoadThread downloadThread = new DownLoadThread(srcFileUrl, destFilePath, offset, fileSize);
			Thread t = new Thread(downloadThread);
			t.setPriority(10);
			t.start();
			try {
				t.join();  //该方法作用:主线程(此处是 main函数执行的线程) 等待该下载线程结束
			} catch (InterruptedException e) {
			}
		}else{
			for (int i = 1; i <= threadCount; i++) {

				DownLoadThread downloadThread = new DownLoadThread(
						srcFileUrl, destFilePath, offset, unitSize);
				Thread t = new Thread(downloadThread);
				t.setPriority(10);
				t.start();
				offset = offset + unitSize;
			}
			if (fileSize % unitSize != 0) {
				// 如果不能整除,则需要再创建一个线程下载剩余字节
				DownLoadThread downloadThread = new DownLoadThread(srcFileUrl, destFilePath, offset, fileSize - unitSize * threadCount);
				Thread t = new Thread(downloadThread);
				t.setPriority(10);
				t.start();
				try {
					t.join(); //该方法作用:主线程(此处是 main函数执行的线程) 等待所有由  主线程产生的下载线程  结束
				} catch (InterruptedException e) {
				}
			}
		}

		long endTime = System.currentTimeMillis();
		System.out.println(endTime);
		System.out.println("下载文件大小为  = " + fileSize2String(fileSize)+ ";  所使用时间  = "+ (endTime - startTime) + " millisecond");
	}

	/**
	 * 获取文件大小
	 */

	private static long getRemoteFileSize(String srcFileUrl) {
		HttpClient httpClient = HttpClientFactory.getInstance().getHttpClient();
		HttpGet httpGet = new HttpGet(srcFileUrl);
		// 发送请求,返回响应
		HttpResponse response = null;

		try {
			response = httpClient.execute(httpGet);
		} catch (ClientProtocolException e) {
		} catch (IOException e) {
		}
		long result = response.getEntity().getContentLength();
		return result;
	}

	/**
	 * 创建指定大小的文件
	 * @param fileName
	 * @param fileSize
	 */
	private static void createFile(String fileName, long fileSize) {
		File newFile = new File(fileName);
		if(newFile.exists())newFile.delete();
		RandomAccessFile raf = null;
		try {
			raf = new RandomAccessFile(newFile, "rw");
			raf.setLength(fileSize);
		} catch (FileNotFoundException e) {
		} catch (IOException e) {
		} finally {
			try {
				if (raf != null) {
					raf.close();
				}
			} catch (IOException e) {
			}
		}

	}

	/**
	 * 获取大小字符串
	 * @param totalSize
	 * @return
	 */
	private static String fileSize2String(long totalSize){
		  String fileTotalSize="";
        DecimalFormat df = new DecimalFormat("0.00");
    	if(totalSize <1024){
    		fileTotalSize=totalSize+"B";
    	}else if(totalSize <1048576){
    		fileTotalSize=df.format((float)totalSize/1024)+"K";
    	}else if(totalSize <1073741824){
    		fileTotalSize=df.format((float)totalSize/1048576)+"M";
    	}else{
    		fileTotalSize=df.format((float)totalSize/1073741824)+"G";
    	}
    	return fileTotalSize;
	}
}

DownLoadThread.java

package com.wl.util;

import java.io.BufferedInputStream;
import java.io.IOException;
import java.net.HttpURLConnection;
import java.net.URL;

public class DownLoadThread implements Runnable {

	private String url = null;// 待下载的文件
	private String file = null;// 本地存储路径
	private long offset = 0;// 偏移量
	private long length = 0;// 分配给本线程的下载字节数

	public DownLoadThread(String url, String file, long offset, long length) {
		this.url = url;
		this.file = file;
		this.offset = offset;
		this.length = length;
	}

	public void run() {
		BufferedInputStream bis = null;
		SaveItemFile saveItemFile = null;
		try {
			HttpURLConnection httpURLConnection = (HttpURLConnection) new URL(
					this.url.replace(" ", "%20")).openConnection();
			httpURLConnection.setRequestMethod("GET");
			httpURLConnection.setRequestProperty("RANGE", "bytes="
					+ this.offset + "-" + (this.offset + this.length - 1));
			bis = new BufferedInputStream(httpURLConnection.getInputStream());

			saveItemFile = new SaveItemFile(file,offset);

			byte[] buff = new byte[1024*8];
			while ((length = bis.read(buff)) > 0 && offset < offset+length ) {
                //写入文件内容,返回最后写入的长度
				offset += saveItemFile.write(buff, 0, (int)length);
            }
		} catch (IOException e) {
		} finally {
			try {
				if (bis != null) {
					bis.close();
				}
				if(saveItemFile!=null){
					saveItemFile.close();
				}
			} catch (IOException e) {
			}

		}

	}
}

HttpClientFactory.java:

package com.wl.util;

import java.util.concurrent.TimeUnit;

import org.apache.http.HttpVersion;
import org.apache.http.client.HttpClient;
import org.apache.http.conn.scheme.PlainSocketFactory;
import org.apache.http.conn.scheme.Scheme;
import org.apache.http.conn.scheme.SchemeRegistry;
import org.apache.http.conn.ssl.SSLSocketFactory;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.impl.conn.PoolingClientConnectionManager;
import org.apache.http.params.BasicHttpParams;
import org.apache.http.params.CoreConnectionPNames;
import org.apache.http.params.HttpParams;
import org.apache.http.params.HttpProtocolParams;

public class HttpClientFactory {

	private HttpClient httpClient = null;

	/**
	 * 本类可能存在的惟一的一个实例
	 */
	private static HttpClientFactory m_instance;

	/**
	 * 静态工厂方法
	 *
	 * @return 返还ReadConfigation 类的单一实例
	 */
	public static HttpClientFactory getInstance() {
		if (null == m_instance) {
			m_instance = new HttpClientFactory();
		}
		return m_instance;
	}

	private HttpClientFactory() {

		// 设置组件参数, HTTP协议的版本,1.1/1.0/0.9
		HttpParams params = new BasicHttpParams();
		HttpProtocolParams.setVersion(params, HttpVersion.HTTP_1_1);
		HttpProtocolParams.setUserAgent(params, "HttpComponents/1.1");
		HttpProtocolParams.setUseExpectContinue(params, true);

		// 设置连接超时时间
		int REQUEST_TIMEOUT = 30 * 1000; // 设置请求超时10秒钟
		int SO_TIMEOUT = 10 * 1000; // 设置等待数据超时时间10秒钟
		// HttpConnectionParams.setConnectionTimeout(params, REQUEST_TIMEOUT);
		// HttpConnectionParams.setSoTimeout(params, SO_TIMEOUT);
		params.setParameter(CoreConnectionPNames.CONNECTION_TIMEOUT,
				REQUEST_TIMEOUT);
		params.setParameter(CoreConnectionPNames.SO_TIMEOUT, SO_TIMEOUT);

		// 设置访问协议
		SchemeRegistry schreg = new SchemeRegistry();
		schreg.register(new Scheme("http", 80, PlainSocketFactory
				.getSocketFactory()));
		schreg.register(new Scheme("https", 443, SSLSocketFactory
				.getSocketFactory()));

		// 多连接的线程安全的管理器
		PoolingClientConnectionManager pccm = new PoolingClientConnectionManager(
				schreg);
		pccm.setDefaultMaxPerRoute(50); // 每个主机的最大并行链接数
		pccm.setMaxTotal(100); // 客户端总并行链接最大数

		httpClient = new DefaultHttpClient(pccm, params);
		httpClient.getConnectionManager().closeIdleConnections(10,
				TimeUnit.SECONDS);

	}

	public DefaultHttpClient getHttpClient() {
		return (DefaultHttpClient) httpClient;
	}

}

SaveItemFile.java:

package com.wl.util;

import java.io.IOException;
import java.io.RandomAccessFile;

public class SaveItemFile {
    //存储文件
    private RandomAccessFile itemFile;

    public SaveItemFile() throws IOException {
        this("", 0);
    }

    /**
     * @param name 文件路径、名称
     * @param pos 写入点位置 position
     * @throws IOException
     */
    public SaveItemFile(String name, long pos) throws IOException {
        itemFile = new RandomAccessFile(name, "rw");//可读可写
        //在指定的pos位置开始写入数据
        itemFile.seek(pos);
    }

    /**
     * <b>function:</b> 同步方法写入文件
     * @author hoojo
     * @createDate 2011-9-26 下午12:21:22
     * @param buff 缓冲数组
     * @param start 起始位置
     * @param length 长度
     * @return
     */
    public int write(byte[] buff, int start, int length) {
        int i = -1;
        try {
            itemFile.write(buff, start, length);
            i = length;
        } catch (IOException e) {
            e.printStackTrace();
        }
        return i;
    }

    public void close() throws IOException {
        if (itemFile != null) {
            itemFile.close();
        }
    }
}

pom.xml

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">

  <modelVersion>4.0.0</modelVersion>
  <groupId>com.filedownload</groupId>
  <artifactId>filedownload</artifactId>
  <version>0.0.1-SNAPSHOT</version>

  <dependencies>

  	<dependency>
         <groupId>org.apache.httpcomponents</groupId>
         <artifactId>com.springsource.org.apache.httpcomponents.httpclient</artifactId>
         <version>4.2.1</version>
     </dependency>

  </dependencies>
</project>

over

多线程上传  未完待续........

时间: 2024-10-05 10:20:57

Java 多线程下载示例的相关文章

最新---java多线程下载文件

import java.io.InputStream; import java.io.RandomAccessFile; import java.net.HttpURLConnection; import java.net.URL; public class Demo { // 定义线程个数 public static int threadCount = 5; public static void main(String[] args) throws Exception { // 1,连接到服务

Android之——多线程下载示例(一)

转载请注明出处:http://blog.csdn.net/l1028386804/article/details/46883927 一.概述 说到Android中的文件下载,Android API中明确要求将耗时的操作放到一个子线程中执行,文件的下载无疑是需要耗费时间的,所以要将文件的下载放到子线程中执行.下面,我们一起来实现一个Android中利用多线程下载文件的小例子. 二.服务端准备 在这个小例子中我以下载有道词典为例,在网上下载有道词典的安装包,在eclipse中新建项目web,将下载的

JAVA 多线程下载及断点续传

断点续传和多线程下载原理是一样的; 关键代码关键位置:即设置断点 http2.setRequestProperty("RANGE","bytes="+startl+"-");//设置断点位置,向服务器请求从文件的哪个字节开始读取.osf.seek(startl);//设置本地文件从哪个字节开始写入. 如果是单线程,则首先要判断下载文件是否已经存在;如果存在则开始断点续传,方法同多线程:因为断点续传是从上次传输中断的字节开始,则首先要得到上次中断的

java多线程下载

多线程下载是通过占有服务器资源来提高速度的.每个线程应该下载一个文件的不同位置,假如现在有一个长度为10的资源,有三个线程,那么第一个线程下载的长度为012,第二个为345,第四个为6789所以问题来了每个线程下载的长度是多少呢?线程的id为0,1,2每个线程下载的数量=总长度/线程数量size=10/3start:id*sizeend:(id+1)*size-1最后一个线程的结束位置为:总长度-1 package down; import java.io.File; import java.i

java 多线程下载功能

import java.io.InputStream; import java.io.RandomAccessFile; import java.net.HttpURLConnection; import java.net.URL; public class Demo { private static int threadCount = 3; /** * 多线程下载测试类 * @param args * @throws Exception */ public static void main(S

Java多线程下载文件

package com.test.download; import java.io.File; import java.io.InputStream; import java.io.RandomAccessFile; import java.net.HttpURLConnection; import java.net.URL; /*  * 多线程下载  */ public class MulThreadDownload {     public static void main(String[]

Java多线程下载器FileDownloader(支持断点续传、代理等功能)

前言 在我的任务清单中,很早就有了一个文件下载器,但一直忙着没空去写.最近刚好放假,便抽了些时间完成了下文中的这个下载器. 介绍 同样的,还是先上效果图吧. Jar包地址位于 FileDownloader 目前实现的主要功能有: 多线程下载 断点续传 自定义头部等 即将完成的包括: 添加代理功能 ... 感觉做了回标题党,代理功能由于时间关系,将在下次更新加入. 关于设置代理,我这篇文章 Java实现Ip代理池 中有具体的设置方法. 另外除了这个代理功能,我也实在不知道下载器能加些啥功能了..

java多线程下载文件和断点下载

多线程,断点下载文件 import java.io.BufferedReader; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.io.RandomAccessFile;

java 多线程下载

1 import java.io.ByteArrayOutputStream; 2 import java.io.InputStream; 3 4 public class StreamTool { 5 /** 6 * 把一个inputstream里面的内容转化成一个byte[] 7 */ 8 public static byte[] getBytes(InputStream is) throws Exception { 9 ByteArrayOutputStream bos = new Byt