`
zhanghongliang_cyj
  • 浏览: 50334 次
  • 性别: Icon_minigender_1
  • 来自: 邯郸
社区版块
存档分类
最新评论

java多线程复制

 
阅读更多
java 实现多线程复制功能,支持中断后继续。

CopyTask.java

package copyFileTest;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.RandomAccessFile;
import java.util.concurrent.Callable;
import java.util.concurrent.CountDownLatch;

public class CopyTask implements Callable<String> {
	// 缓冲区大小
	private int bufferSize = 10240;

	private CountDownLatch latch;
	private RandomAccessFile file = null;
	private RandomAccessFile tempFile = null;
	private RandomAccessFile inputFile = null;

	private int id;
	private long startPosition;
	private long endPosition;
	private long currentPosition;

	public CopyTask(File file, File tmpFile, File inputFile, int id,
			CountDownLatch latch, int bufferSize) {
		try {
			this.file = new RandomAccessFile(file, "rw");
			this.tempFile = new RandomAccessFile(tmpFile, "rw");
			this.inputFile = new RandomAccessFile(inputFile, "r");
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		}
		this.id = id;
		this.latch = latch;
		this.bufferSize = bufferSize;
	}

	public String call() throws Exception {

		try {
			tempFile.seek((id - 1) * 28);
			tempFile.readInt();
			this.startPosition = tempFile.readLong();
			this.endPosition = tempFile.readLong();
			this.currentPosition = tempFile.readLong();
		} catch (IOException e) {
			e.printStackTrace();
		}

		System.out.println("Thread " + id + " begin!");

		while (true) {
			try {
				tempFile.seek(id * 28 - 8);
				if (currentPosition < endPosition) {
					inputFile.seek(currentPosition);

					file.seek(currentPosition);

					int len = 0;
					byte[] b = new byte[bufferSize];
					while ((len = inputFile.read(b)) != -1) {
						file.write(b, 0, len);

						currentPosition += len;
						tempFile.seek(id * 28 - 8);
						tempFile.writeLong(currentPosition);

						if (currentPosition > endPosition) {
							break;
						}
					}
					System.out.println("Thread " + id + " startPosition="
							+ startPosition + ",endPosition=" + endPosition
							+ ",currentPosition=" + currentPosition);

				}
				System.out.println("Thread " + id + " finished.");
				break;
			} catch (IOException e) {
				e.printStackTrace();
			} finally {
				file.close();
				tempFile.close();
				inputFile.close();
			}
		}
		latch.countDown();
		return "finish";
	}
}



CopyFileTest.java
package copyFileTest;

import java.io.DataOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.math.BigDecimal;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class CopyFileTest {
	// 线程数
	private int poolSize = 10;
	// 每个线程的缓冲区大小
	public int bufferSize = 10240;
	private int loopSize = 10000; // 每个线程循环读的次数

	/**
	 * 复制文件
	 * 
	 * @param fileSource
	 *            要复制的文件
	 * @param fileTarget
	 *            要复制到的文件路径
	 */
	public void copy(String fileSource, String fileTarget) {
		long startTime = System.currentTimeMillis();
		File file = null;
		File tempFile = null;
		File targetFile = null;
		CountDownLatch latch;
		ExecutorService pool = Executors.newCachedThreadPool();
		long contentLength = 0;
		long threadLength = 0;
		try {
			new File(fileTarget).mkdirs();
			file = new File(fileSource);
			targetFile = new File(fileTarget + File.separator + file.getName());
			tempFile = new File(fileTarget + File.separator + "_temp");

			// 得到content的长度
			contentLength = file.length();
			poolSize = this.getPoolSize(contentLength);
			System.out.println("total length=" + contentLength
					+ " use ThreadSize:" + poolSize);

			threadLength = loopSize * bufferSize;

			if (file.exists() && tempFile.exists()) {
				// 如果文件已存在,根据临时文件中记载的线程数量,继续上次的任务
				int tmpFileLength = (int) tempFile.length() / 28 + 1;
				latch = new CountDownLatch(tmpFileLength);
				for (int i = 1; i < tmpFileLength; i++) {
					pool.submit(new CopyTask(targetFile, tempFile, file, i,
							latch, bufferSize));
				}
			} else {
				// 如果下载的目标文件不存在,则创建新文件
				latch = new CountDownLatch(poolSize);
				targetFile.createNewFile();
				tempFile.createNewFile();
				DataOutputStream os = new DataOutputStream(
						new FileOutputStream(tempFile));
				for (int i = 0; i < this.poolSize; i++) {
					os.writeInt(i + 1);
					os.writeLong(i * threadLength);
					if (i == this.poolSize - 1) {// 最后一个线程的结束位置应为文件末端
						os.writeLong(contentLength);
					} else {
						os.writeLong((i + 1) * threadLength);
					}
					os.writeLong(i * threadLength);
					pool.submit(new CopyTask(targetFile, tempFile, file, i + 1,
							latch, bufferSize));
				}
				os.close();
			}
			// 等待下载任务完成
			latch.await();
			// 删除临时文件
			System.out.println("删除临时文件" + tempFile.delete());
		} catch (IOException e) {
			e.printStackTrace();
		} catch (InterruptedException e) {
			e.printStackTrace();
		} finally {
			pool.shutdown();
			System.out.println("完成复制,所用时:"
					+ (System.currentTimeMillis() - startTime));
		}
	}

	/**
	 * 根据总大小 缓存区与每个线程默认循环次数,判断用几个线程
	 * 
	 * @param contentLength
	 * @return
	 * 
	 */
	public int getPoolSize(long contentLength) {
		int poolSize = 1;
		BigDecimal contentBig = new BigDecimal(contentLength);
		BigDecimal bufferBig = new BigDecimal(bufferSize);
		BigDecimal loopBig = new BigDecimal(loopSize);

		poolSize = contentBig.divide(bufferBig.multiply(loopBig), 0,
				BigDecimal.ROUND_HALF_UP).intValue();

		return poolSize;
	}

	public static void main(String[] args) {
		String fileSource = "D:\\add.rar"; // 要复制的文件
		String fileTarget = "D:\\copyTest";
		new CopyFileTest().copy(fileSource, fileTarget);
	}
}


分享到:
评论

相关推荐

    java多线程复制文件

    java多线程复制文件

    Java 单线程复制文件和多线程复制文件的比较

    Java 单线程复制文件和使用RandomAccessFile多线程复制文件的比较,对应博客地址为http://blog.csdn.net/zmichealchow/article/details/38687431

    java多线程复制文件的实例代码

    Java多线程复制文件的实例代码详解 Java多线程复制文件的实例代码是Java编程语言中的一种高级技术,用于快速复制大文件。该技术通过多线程并发访问文件,提高了文件复制的速度和效率。在这个示例代码中,我们将详细...

    C语言八皇后及java多线程复制文件

    8*8的国际象棋上有八个皇后他们不能在同一行。同一列和斜对角和java中用多线程复制文件

    Java多线程网络爬虫(时光网为例)源码

    Java多线程网络爬虫是一种高效地从互联网上抓取数据的技术,特别是在处理大量网页时,多线程能显著提高爬虫的效率。本项目以时光网(Mtime)为例,展示如何使用Java实现这样的爬虫。时光网是一个提供电影、电视剧、...

    java多线程面试题59题集合

    Java多线程是Java编程中的核心概念,它允许程序同时执行多个任务,从而提升系统效率。在面试中,对Java多线程的理解和熟练运用往往成为衡量开发者技能水平的重要标准。以下是对Java多线程面试题59题集合中可能涉及的...

    java多线程教程 java多线程教程

    Java多线程教程详解 Java多线程是Java编程中不可或缺的一部分,它允许程序同时执行多个任务,提高程序效率和响应速度。理解并熟练运用Java的多线程机制是成为一个专业Java开发人员的关键技能。 一、线程的概念与...

    深入浅出Java多线程.pdf

    ### 深入浅出Java多线程.pdf #### 知识点概览 本PDF文档涉及了Java多线程的全面介绍,分为基础篇、原理篇和JDK工具篇三个部分,旨在帮助读者深入了解Java多线程的概念、原理及实践应用。 #### 基础篇 **1. 进程...

    Java多线程文件复制器

    Java实现多线的文件复制(界面)。 可以选择复制文件的路径,和复制到某处的路径。可以选择线程数量。

    Java多线程技术

    Java多线程技术是Java编程语言中的一个重要部分,它允许程序员创建多个线程来执行多个任务,这样可以有效地利用系统资源,提高程序的执行效率。在Java中,多线程的实现主要有两种方式:一种是继承Thread类,另一种是...

    Java多线程优化百万级数据

    本篇将深入探讨如何利用Java多线程技术来优化这种高负载场景。 首先,理解Java多线程的基础至关重要。在Java中,线程是程序执行的最小单元,可以通过实现`Runnable`接口或继承`Thread`类来创建线程。创建多线程的...

    Java多线程安全集合

    在Java编程中,多线程安全集合是程序员在并发环境下处理数据共享时必须考虑的关键概念。这些集合确保了在多个线程访问时的数据一致性、完整性和安全性,避免了竞态条件、死锁和其他并发问题。Java提供了一系列的线程...

    java小项目多线程多线程 复制文件 冒泡排序 群聊

    在Java编程领域,多线程是一项关键技能,它允许程序同时执行多个任务,提升系统效率。多线程在处理并发操作、优化资源利用率以及构建高效应用程序方面起着至关重要的作用。在Java中,可以通过实现Runnable接口或者...

    JAVA多线程编程详解

    ### JAVA多线程编程详解 #### 一、深入理解多线程 多线程机制是现代编程语言中处理并发操作的关键技术之一,尤其在Java中,多线程提供了高效的资源利用方式,允许程序中多个指令流同时运行,提高程序执行效率。每...

    java多线程.pdf

    Java多线程是一种允许同时执行多个线程的编程技术,它允许利用多核处理器的计算能力,提高应用程序的性能和响应能力。在介绍Java多线程的基本知识之前,首先提到的是Java多线程的实现方式。在Java中,创建线程主要有...

    多线程对文件读写操作(java)

    在Java编程中,多线程技术是提升程序执行效率的关键之一,特别是在进行文件读写操作时。本主题将深入探讨如何使用多线程来优化文件的读取和写入过程,以及需要注意的相关问题。 首先,我们需要理解单线程与多线程在...

    Java多线程-知识点梳理和总结-超详细-面试知识点.docx

    "Java多线程-知识点梳理和总结-超详细-面试知识点" Java多线程是Java编程语言中最基本也是最重要的概念之一。多线程编程可以提高程序的执行效率、改善用户体验和提高系统的可扩展性。但是,多线程编程也存在一些...

    【IT十八掌徐培成】Java基础第17天-04.多线程复制-1avi.zip

    总的来说,徐培成老师的这堂课将帮助初学者深入理解Java多线程编程的基础知识,掌握多线程复制的具体实现,以及如何在实际开发中有效地利用多线程提升程序性能。通过学习,你将能够创建安全、高效的多线程Java应用,...

Global site tag (gtag.js) - Google Analytics