`

jdk6.0从入门到精通-----chapter7线程(3)多线程下载程序

阅读更多
主程序,获得欲下载文件的大小,根据其大小分配线程数量和下载的偏移量

package mulithreaddownload;

import java.net.URL;
import java.net.HttpURLConnection;
import java.io.File;
import java.io.RandomAccessFile;
import java.io.IOException;

public class DownloadManager {
	static final long unitSize = 100 * 1024; // 分配给每个下载线程的字节数

	public static void main(String[] args) throws IOException {
		if (args.length != 2) {
			System.out
					.println("Usage java DownloadManager URL local_file_name");
			return;
		}
		DownloadManager downloadManager = new DownloadManager();
		downloadManager.doDownload(args[0], args[1]);
	}

	public void doDownload(String remoteFileUrl, String localFileName)
			throws IOException {
		long fileSize = this.getRemoteFileSize(remoteFileUrl);
		this.createFile(localFileName, fileSize);
		long threadCount = fileSize / unitSize;
		System.out.println("共启动线程"
				+ (fileSize % unitSize == 0 ? threadCount : threadCount + 1)
				+ "个");
		long offset = 0;
		if (fileSize <= unitSize) // 如果远程文件尺寸小于等于unitSize
		{
			DownloadThread downloadThread = new DownloadThread(remoteFileUrl,
					localFileName, offset, fileSize);
			downloadThread.start();
		} else // 如果远程文件尺寸大于unitSize
		{
			for (int i = 1; i <= threadCount; i++) {
				DownloadThread downloadThread = new DownloadThread(
						remoteFileUrl, localFileName, offset, unitSize);
				downloadThread.start();
				offset = offset + unitSize;
			}
			if (fileSize % unitSize != 0) // 如果不能整除,则需要再创建一个线程下载剩余字节
			{
				DownloadThread downloadThread = new DownloadThread(
						remoteFileUrl, localFileName, offset, fileSize
								- unitSize * threadCount);
				downloadThread.start();
			}
		}
	}

	// 获取远程文件尺寸
	private long getRemoteFileSize(String remoteFileUrl) throws IOException {
		long result = 0;
		HttpURLConnection httpConnection = (HttpURLConnection) new URL(
				remoteFileUrl).openConnection();
		httpConnection.setRequestMethod("HEAD");
		for (int i = 1; i <= 10; i++) {
			if (httpConnection.getHeaderFieldKey(i).equalsIgnoreCase(
					"Content-Length")) {
				result = Long.parseLong(httpConnection.getHeaderField(i));
				break;
			}
		}
		return result;
	}

	// 创建指定大小的文件
	private void createFile(String fileName, long fileSize) throws IOException {
		File newFile = new File(fileName);
		RandomAccessFile raf = new RandomAccessFile(newFile, "rw");
		raf.setLength(fileSize);
		raf.close();
	}
}


下载的具体实现有线程实现

package mulithreaddownload;

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

public class DownloadThread extends Thread {
	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;
		System.out.println("偏移量=" + offset + ";字节数=" + length);
	}

	public void run() {
		try {
			HttpURLConnection httpConnection = (HttpURLConnection) new URL(
					this.url).openConnection();
			httpConnection.setRequestMethod("GET");
			httpConnection.setRequestProperty("RANGE", "bytes=" + this.offset
					+ "-" + (this.offset + this.length - 1));
			BufferedInputStream bis = new BufferedInputStream(httpConnection
					.getInputStream());
			byte[] buff = new byte[1024];      // 分段读取,防止内容泄露
			int bytesRead;
			while (-1 != (bytesRead = bis.read(buff, 0, buff.length))) {
				this.writeFile(this.file, this.offset, buff, bytesRead);
				this.offset = this.offset + bytesRead;
			}
		} catch (IOException ioe) {
			ioe.printStackTrace();
		}
	}

	// 将字节数组以随机存取方式写入文件
	// fileName是被写入的文件
	// offset代表写入文件的位置偏移量
	// bytes是待写入的字节数组
	// realLength是实际需要写入的字节数(realLength<=bytes.length)
	private void writeFile(String fileName, long offset, byte[] bytes,
			int realLength) throws IOException {
		File newFile = new File(fileName);
		RandomAccessFile raf = new RandomAccessFile(newFile, "rw");
		raf.seek(offset);
		raf.write(bytes, 0, realLength);
		raf.close();
	}
}



分享到:
评论

相关推荐

    jdk6.0从入门到精通-----chapter7线程

    《JDK 6.0线程入门到精通——Chapter 7》 在Java开发中,线程是程序执行的最小单元,它使得一个程序能够同时处理多个任务,从而提高了程序的效率和响应性。在JDK 6.0中,线程的管理和使用有了更加完善的特性,对于...

    jdk6.0从入门到精通-----chapter8并发多线程(1)(源码下载)

    本章“jdk6.0从入门到精通-----chapter8并发多线程(1)”着重讲解了Java 6中关于多线程的基本知识和实践技巧。通过源码下载,读者可以更直观地理解多线程的实现方式。 首先,我们要理解什么是多线程。在单线程环境...

    jdk6.0从入门到精通-----chapter17动态编程

    《JDK 6.0从入门到精通——Chapter 17 动态编程》 在Java编程领域,JDK 6.0版本引入了许多新特性,其中动态编程是提升开发效率和灵活性的重要方面。本章将深入探讨动态编程的概念、用途以及如何在JDK 6.0中利用这些...

    jdk6.0从入门到精通-----chapter18与动态语言结合

    标题中的“jdk6.0从入门到精通-----chapter18与动态语言结合”指的是Java开发工具包(JDK)6.0版本中的一个章节,主要探讨了如何将Java与动态编程语言集成。在Java 6中,引入了一个重要的特性,即Java平台标准版6...

    jdk6.0从入门到精通-----chapter5网络编程 新I/O(含源码下载)

    在Java编程领域,JDK(Java Development Kit)是开发和运行Java应用程序的...总的来说,"JDK6.0从入门到精通-----chapter5网络编程 新I/O"是一个极好的学习资源,无论你是初学者还是有经验的开发者,都能从中获益良多。

    (源码下载)jdk6.0从入门到精通-----chapter2--输入输出,克隆对象

    标题 "(源码下载)jdk6.0从入门到精通-----chapter2--输入输出,克隆对象" 提供了我们要探讨的主题,即Java中的输入输出流(I/O Stream)和对象克隆。在这个章节中,我们将深入理解这两个关键概念。 **输入输出流...

    jdk6.0从入门到精通-----chapter4--文件目录操作

    在Java编程语言中,JDK(Java Development Kit)是核心组件,它包含了开发和运行Java应用程序所需的工具和...同时,随着Java版本的更新,如JDK 7和8引入了更多的文件操作改进,开发者也需要持续学习和掌握最新的技术。

    jdk6.0从入门到精通-----chapter16反射机制-spring AOP

    在Java编程领域,JDK6.0是一个重要的版本,它为开发者提供了丰富的特性和改进。本章我们将深入探讨“反射机制”以及如何结合Spring AOP(面向切面编程)进行应用。反射是Java中的一种强大工具,允许程序在运行时检查...

    jdk 6.0 jdk-6u10-rc2-bin-b32-windows-i586-p-12_sep_2008(微信开发平台开发JDK)

    微信开发平台开发工具 JDK jdk 6.0 jdk-6u10-rc2-bin-b32-windows-i586-p-12_sep_2008

    官方JDK6.0中文版

    - 首先,从官方或可信渠道下载JDK 6.0的安装程序。 - 运行安装程序,按照提示完成安装过程。 - 配置环境变量,如JAVA_HOME指向JDK安装目录,PATH添加bin子目录,确保系统能够找到Java命令。 - 检验安装是否成功,...

    JDK6.0+中文文档-lytim24.part1.rar

    java6.0文档chm版,分成三部分,分别为JDK6.0+中文文档-lytim24.part1.rar、JDK6.0+中文文档-lytim24.part2.rar、JDK6.0+中文文档-lytim24.part3.rar

    JDK 6.0.zip

    这个压缩包“JDK 6.0.zip”显然是为了方便用户下载和安装这一特定版本的JDK。 JDK 6.0在2006年发布,它是Java SE(Standard Edition)的一部分,主要用于桌面应用开发。这一版本引入了许多新特性和改进,包括: 1....

    jdk7 jdk-7u80-linux-x64 网盘下载

    tar -zxvf jdk-7u80-linux-x64.tar.gz ``` 这会创建一个名为`jdk1.7.0_80`的目录,其中包含了JDK的所有文件。 ##### 4.3 设置环境变量 为了让操作系统能够找到JDK,需要将JDK的路径添加到系统的环境变量中。可以...

    JDK6.0u10b32-windows-

    这个是安装开发工具java jdk 有很多用途

    jdk-7u80-windows-x64.exe

    【标题】"jdk-7u80-windows-x64.exe" 指的是Java Development Kit (JDK) 的第7个版本更新80的64位Windows安装程序。JDK是Oracle公司提供的一个用于开发和运行Java应用程序的核心工具集。 【描述】"jdk-7u80-windows...

    jdk6.0中文文档

    1. **概述**:介绍JDK 6.0的基本概念、系统需求和安装指南,帮助初学者快速入门。 2. **Java语言规范**:详细解释了Java语言的语法和特性,包括类、对象、接口、异常处理等。 3. **API参考**:这是文档的核心部分...

    jdk-8u311-windows-x64.exe

    jdk-8u311-windows-x64.exe jdk-8u311-windows-x64.exe.zip jdk-8u311-windows-x64.exe jdk-8u311-windows-x64.exe.zip jdk-8u311-windows-x64.exe jdk-8u311-windows-x64.exe.zip jdk-8u311-windows-x64.exe jdk-8u...

    jdk-7u60-windows-x64下载地址

    该资源为jdk-7u60-windows-x64.exe jdk1.7 64位 欢迎大家下载!

    jdk-7u80-windows-x64.exe 【官方下载的jdk1.7、jdk7,windows 64位版】

    在这个特定的压缩包中,我们找到了"jdk-7u80-windows-x64.exe",这正是JDK 1.7的64位版本,适用于Windows操作系统。这个版本的JDK是Java 7的更新版本,编号为u80,代表Update 80,意味着它包含了自初始发布以来的...

    jdk8安装包: jdk-8u202-windows-x64

    1. 下载与操作系统匹配的JDK安装包,如"jdk-8u202-windows-x64.exe"。 2. 双击执行安装程序,按照向导指示进行操作,选择安装路径。 3. 在安装过程中,确保勾选"将Java添加到系统PATH"选项,以便在命令行中直接运行...

Global site tag (gtag.js) - Google Analytics