`

java 计算文件目录下文件总大小的几种多线程并发实现

    博客分类:
  • java
 
阅读更多

1.单线程实现

package com.mime;

import java.io.File;

public class TotalFileSizeSequential {
	private long getTotalSizeOfFilesInDir(final File file) {
		if (file.isFile())
			return file.length();
		final File[] children = file.listFiles();
		long total = 0;
		if (children != null)
			for (final File child : children)
				total += getTotalSizeOfFilesInDir(child);
		return total;
	}

	public static void main(final String[] args) {
		final long start = System.nanoTime();
		final long total = new TotalFileSizeSequential()
				.getTotalSizeOfFilesInDir(new File(args[0]));
		final long end = System.nanoTime();
		System.out.println("Total Size: " + total);
		System.out.println("Time taken: " + (end - start) / 1.0e9);
	}
}

 2使用Executors.newFixedThreadPool和callable 多线程实现

package com.mime;

import java.io.File;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;

public class ConcurrentTotalFileSize {
	class SubDirectoriesAndSize {
		final public long size;
		final public List<File> subDirectories;

		public SubDirectoriesAndSize(final long totalSize,
				final List<File> theSubDirs) {
			size = totalSize;
			subDirectories = Collections.unmodifiableList(theSubDirs);
		}
	}

	private SubDirectoriesAndSize getTotalAndSubDirs(final File file) {
		long total = 0;
		final List<File> subDirectories = new ArrayList<File>();
		if (file.isDirectory()) {
			final File[] children = file.listFiles();
			if (children != null)
				for (final File child : children) {
					if (child.isFile())
						total += child.length();
					else
						subDirectories.add(child);
				}
		}
		return new SubDirectoriesAndSize(total, subDirectories);
	}

	private long getTotalSizeOfFilesInDir(final File file)
			throws InterruptedException, ExecutionException, TimeoutException {
		final ExecutorService service = Executors.newFixedThreadPool(100);
		try {
			long total = 0;
			final List<File> directories = new ArrayList<File>();
			directories.add(file);
			while (!directories.isEmpty()) {
				final List<Future<SubDirectoriesAndSize>> partialResults = new ArrayList<Future<SubDirectoriesAndSize>>();
				for (final File directory : directories) {
					partialResults.add(service
							.submit(new Callable<SubDirectoriesAndSize>() {
								public SubDirectoriesAndSize call() {
									return getTotalAndSubDirs(directory);
								}
							}));
				}
				directories.clear();
				for (final Future<SubDirectoriesAndSize> partialResultFuture : partialResults) {
					final SubDirectoriesAndSize subDirectoriesAndSize = partialResultFuture
							.get(100, TimeUnit.SECONDS);
					directories.addAll(subDirectoriesAndSize.subDirectories);
					total += subDirectoriesAndSize.size;
				}
			}
			return total;
		} finally {
			service.shutdown();
		}
	}

	public static void main(final String[] args) throws InterruptedException,
			ExecutionException, TimeoutException {
		final long start = System.nanoTime();
		final long total = new ConcurrentTotalFileSize()
				.getTotalSizeOfFilesInDir(new File("/home"));
		final long end = System.nanoTime();
		System.out.println("Total Size: " + total);
		System.out.println("Time taken: " + (end - start) / 1.0e9);
	}
}

 32使用Executors.newFixedThreadPool和callable 多线程的另外一种实现

import java.io.File;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;

public class NaivelyConcurrentTotalFileSize {
	private long getTotalSizeOfFilesInDir(final ExecutorService service,
			final File file) throws InterruptedException, ExecutionException,
			TimeoutException {
		if (file.isFile())
			return file.length();

		long total = 0;
		final File[] children = file.listFiles();

		if (children != null) {
			final List<Future<Long>> partialTotalFutures = new ArrayList<Future<Long>>();
			for (final File child : children) {
				partialTotalFutures.add(service.submit(new Callable<Long>() {
					public Long call() throws InterruptedException,
							ExecutionException, TimeoutException {
						return getTotalSizeOfFilesInDir(service, child);
					}
				}));
			}

			for (final Future<Long> partialTotalFuture : partialTotalFutures)
				total += partialTotalFuture.get(100, TimeUnit.SECONDS);

		}

		return total;

	}

	private long getTotalSizeOfFile(final String fileName)
			throws InterruptedException, ExecutionException, TimeoutException {
		final ExecutorService service = Executors.newFixedThreadPool(100);
		try {
			return getTotalSizeOfFilesInDir(service, new File(fileName));
		} finally {
			service.shutdown();
		}
	}

	public static void main(final String[] args) throws InterruptedException,
			ExecutionException, TimeoutException {
		final long start = System.nanoTime();
		final long total = new NaivelyConcurrentTotalFileSize()
				.getTotalSizeOfFile(args[0]);
		final long end = System.nanoTime();
		System.out.println("Total Size: " + total);
		System.out.println("Time taken: " + (end - start) / 1.0e9);
	}
}
 

4.使用CountDownLatch和AtomicLong实现多线程下的并发控制

package com.mime;

import java.io.File;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicLong;

public class ConcurrentTotalFileSizeWLatch {
	private ExecutorService service;
	final private AtomicLong pendingFileVisits = new AtomicLong();
	final private AtomicLong totalSize = new AtomicLong();
	final private CountDownLatch latch = new CountDownLatch(1);

	private void updateTotalSizeOfFilesInDir(final File file) {
		long fileSize = 0;
		if (file.isFile())
			fileSize = file.length();
		else {
			final File[] children = file.listFiles();
			if (children != null) {
				for (final File child : children) {
					if (child.isFile())
						fileSize += child.length();
					else {
						pendingFileVisits.incrementAndGet();
						service.execute(new Runnable() {
							public void run() {
								updateTotalSizeOfFilesInDir(child);
							}
						});
					}
				}
			}
		}
		totalSize.addAndGet(fileSize);
		if (pendingFileVisits.decrementAndGet() == 0)
			latch.countDown();
	}

	private long getTotalSizeOfFile(final String fileName)
			throws InterruptedException {
		service = Executors.newFixedThreadPool(100);
		pendingFileVisits.incrementAndGet();
		try {
			updateTotalSizeOfFilesInDir(new File(fileName));
			latch.await(100, TimeUnit.SECONDS);
			return totalSize.longValue();
		} finally {
			service.shutdown();
		}
	}

	public static void main(final String[] args) throws InterruptedException {
		final long start = System.nanoTime();
		final long total = new ConcurrentTotalFileSizeWLatch()
				.getTotalSizeOfFile("/home");
		final long end = System.nanoTime();
		System.out.println("Total Size: " + total);
		System.out.println("Time taken: " + (end - start) / 1.0e9);
	}
}

 5.使用BlockingQueue和AtomicLong的实现

package com.mime;

import java.io.File;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicLong;

public class ConcurrentTotalFileSizeWQueue {
	private ExecutorService service;
	final private BlockingQueue<Long> fileSizes = new ArrayBlockingQueue<Long>(
			500);
	final AtomicLong pendingFileVisits = new AtomicLong();

	private void startExploreDir(final File file) {
		pendingFileVisits.incrementAndGet();
		service.execute(new Runnable() {
			public void run() {
				exploreDir(file);
			}
		});
	}

	private void exploreDir(final File file) {
		long fileSize = 0;
		if (file.isFile())
			fileSize = file.length();
		else {
			final File[] children = file.listFiles();
			if (children != null)
				for (final File child : children) {
					if (child.isFile())
						fileSize += child.length();
					else {
						startExploreDir(child);
					}
				}
		}
		try {
			fileSizes.put(fileSize);
		} catch (Exception ex) {
			throw new RuntimeException(ex);
		}
		pendingFileVisits.decrementAndGet();
	}

	private long getTotalSizeOfFile(final String fileName)
			throws InterruptedException {
		service = Executors.newFixedThreadPool(100);
		try {
			startExploreDir(new File(fileName));
			long totalSize = 0;
			while (pendingFileVisits.get() > 0 || fileSizes.size() > 0) {
				final Long size = fileSizes.poll(10, TimeUnit.SECONDS);
				totalSize += size;
			}
			return totalSize;
		} finally {
			service.shutdown();
		}
	}

	public static void main(final String[] args) throws InterruptedException {
		final long start = System.nanoTime();
		final long total = new ConcurrentTotalFileSizeWQueue()
				.getTotalSizeOfFile("/home");
		final long end = System.nanoTime();
		System.out.println("Total Size: " + total);
		System.out.println("Time taken: " + (end - start) / 1.0e9);
	}
}

 6,使用jdk7的ForkJoin来实现

package com.mime;

import java.io.File;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ForkJoinPool;
import java.util.concurrent.ForkJoinTask;
import java.util.concurrent.RecursiveTask;

public class FileSize {
	private final static ForkJoinPool forkJoinPool = new ForkJoinPool();

	private static class FileSizeFinder extends RecursiveTask<Long> {
		final File file;

		public FileSizeFinder(final File theFile) {
			file = theFile;
		}

		@Override
		public Long compute() {
			long size = 0;
			if (file.isFile()) {
				size = file.length();
			} else {
				final File[] children = file.listFiles();
				if (children != null) {
					List<ForkJoinTask<Long>> tasks = new ArrayList<ForkJoinTask<Long>>();
					for (final File child : children) {
						if (child.isFile()) {
							size += child.length();
						} else {
							tasks.add(new FileSizeFinder(child));
						}
					}
					for (final ForkJoinTask<Long> task : invokeAll(tasks)) {
						size += task.join();
					}
				}
			}
			return size;
		}
	}

	public static void main(final String[] args) {
		final long start = System.nanoTime();
		final long total = forkJoinPool.invoke(new FileSizeFinder(new File("/home")));
		final long end = System.nanoTime();
		System.out.println("Total Size: " + total);
		System.out.println("Time taken: " + (end - start) / 1.0e9);
	}
}
 
1
0
分享到:
评论
1 楼 jarorwar 2012-12-12  
不错啊

相关推荐

    java 多线程并发实例

    在Java编程中,多线程并发是提升程序执行效率、充分利用多核处理器资源的重要手段。本文将基于"java 多线程并发实例"这个主题,深入探讨Java中的多线程并发概念及其应用。 首先,我们要了解Java中的线程。线程是...

    java实现多线程文件传输

    在Java编程语言中,实现多线程文件传输是一种优化程序性能、提高系统资源利用率的有效方法。多线程允许我们同时处理多个任务,这对于大文件传输或需要并行处理的场景尤其有用。本篇文章将深入探讨如何使用Java实现多...

    Java多线程并发实战

    ### Java多线程并发实战知识点解析 #### 一、引言 在计算机科学领域,**多线程**和**并发**技术是现代软件开发中不可或缺的一部分。随着处理器核心数量的增加,利用多线程和并发可以显著提高应用程序的性能和响应...

    java多线程、并发及线程池介绍收藏的几篇文档

    Java多线程、并发以及线程池是Java编程中至关重要的概念,特别是在处理高并发、高性能的系统设计时。以下是对这些主题的详细说明: 1. **Java 程序中的多线程** - 多线程允许一个程序同时执行多个任务,提高程序...

    java 多线程下载 (单文件)

    Java多线程下载技术主要应用于提高大文件下载的效率,通过将文件分割成多个部分,同时启动多个线程分别下载这些部分,从而实现并行下载,加快下载速度。以下是对这个主题的详细解释: 1. **Java多线程基础**: 在...

    多线程并发处理数据的问题

    以《多线程并发处理数据的问题》为主题,结合提供的文件名,如SmsSendClientBatchPool.java、SmsSendClientBatchNew.java、SmsSendClientBatch.java,我们可以推测这可能是关于批量发送短信服务的多线程实现。...

    多线程并发执行任务

    在IT领域,多线程并发执行任务是一种常见的优化策略,特别是在服务器端开发、实时系统以及高性能计算中。本文将深入探讨多线程并发执行任务的相关知识点,并基于提供的`MyThread.java`文件,来分析和理解如何在Java...

    Java多线程并发访问解决方案

    本文将深入探讨Java中的多线程并发访问解决方案,主要围绕以下几个核心知识点进行阐述: 1. **线程同步机制**: - **synchronized关键字**:Java中的synchronized提供了一种内置锁机制,它可以保证同一时间只有一...

    java多线程分页查询

    ### Java多线程分页查询知识点详解 #### 一、背景与需求分析 在实际的软件开发过程中,尤其是在处理大量数据时,如何高效地进行数据查询成为了一个关键问题。例如,在一个用户众多的社交平台上,当用户需要查看...

    Java多线程知识点总结

    线程池是一种多线程处理形式,它将线程和任务的概念分离开来,能够有效管理线程资源,减少线程创建和销毁的开销,提高程序性能。Java中可以通过Executors类快速创建线程池。 随着Java版本的更新,Java也引入了新的...

    java多线程下载源代码

    Java多线程下载是利用Java编程语言实现的一种高效下载大文件的技术。在传统的单线程下载方式中,如果网络环境不稳定或文件较大,下载过程可能会很慢,甚至中断。而多线程下载则是将文件分割成多个部分,每个部分由一...

    java多线程下载文件源码

    这可以通过计算文件总大小除以每个线程下载的块大小来实现。 3. **并发下载**: - 每个线程负责下载一个文件块。创建线程时,每个线程需要知道其对应的下载起始位置和结束位置,以确保各个线程不会相互干扰。 4. ...

    java写的多线程下载程序源码

    Java编写的多线程下载程序源码是一种利用Java语言特性实现高效大文件下载的技术。在这一程序中,主要涉及到了Java的多线程处理和网络编程两大核心知识点。 首先,让我们深入理解Java的多线程。Java提供了丰富的多...

    对java的BitSet的多线程并发的探索

    在多线程并发环境中,对BitSet的操作需要特别注意,因为位操作本身是原子性的,但BitSet的大部分方法并不是线程安全的。这篇博文主要探讨了如何在多线程环境下正确地使用Java的BitSet。 首先,我们要理解BitSet的...

    Java多线程与并发库高级应用

    为了更好地理解Java多线程与并发库的实际应用,我们可以考虑一个具体的案例——使用`ExecutorService`和`Future`实现一个简单的下载文件并合并的功能。 假设我们需要从网络上下载多个小文件,并将它们合并成一个大...

    JAVA单线程多线程

    ### JAVA中的单线程与多线程概念解析 #### 单线程的理解 在Java编程环境中,单线程指的是程序执行过程中只有一个线程在运行。这意味着任何时刻只能执行一个任务,上一个任务完成后才会进行下一个任务。单线程模型...

    Java多线程编程

    在Java中,多线程主要通过`Thread`类和并发工具来实现,接下来我们将深入探讨这些关键知识点。 1. **Thread类**:Java中的`Thread`类是线程的基础,它代表了程序中的一个执行流。创建一个新的线程通常有两种方式:...

    java socket多线程文件上传下载实例项目

    Java Socket多线程文件上传下载实例项目是一种基于Java网络编程技术实现的,旨在处理大量并发连接的文件传输服务。在本项目中,Socket是客户端与服务器之间通信的基础,它允许两个应用程序通过网络交换数据。多线程...

    java多线程下载器

    Java多线程下载器是一种利用Java编程语言实现的高效文件下载工具,它通过将大文件分割成多个小部分,然后创建多个线程同时下载这些部分,以提高下载速度。这种技术在处理大文件或者网络带宽有限的情况下尤其有用,...

Global site tag (gtag.js) - Google Analytics