在 Java 中,可以使用多线程并行读取多个文件以提高文件读取性能,需要我们掌握多线程一些基本用法。
一、ExecutorService
ExecutorService
是 Java 标准库中的一个接口,它提供了一个用于管理和控制线程执行的高级工具,封装了线程的创建、调度、执行和监控。ExecutorService
通常用于执行异步任务、并发编程以及并行计算。
ExecutorService
接口继承自 Executor
接口,它引入了一些管理和控制线程池的方法。主要的实现类是 ThreadPoolExecutor
。
1、submit(Runnable task)
:提交一个可运行的任务给执行器,并返回一个表示任务的未来结果的 Future
对象。可以使用 Future
来检查任务是否完成,获取任务的执行结果。
ExecutorService executor = Executors.newFixedThreadPool(5);
Future<?> future = executor.submit(() -> {
// 执行任务
});
2、submit(Callable<T> task)
:与 submit(Runnable task)
类似,但可以提交一个带有返回值的任务。
ExecutorService executor = Executors.newFixedThreadPool(5);
Future<Integer> future = executor.submit(() -> {
// 执行带有返回值的任务
return 42;
});
3、invokeAll(Collection<? extends Callable<T>> tasks)
:提交一组带有返回值的任务,返回包含所有任务执行结果的 Future
列表。这个方法会阻塞直到所有任务完成。
ExecutorService executor = Executors.newFixedThreadPool(5);
List<Callable<Integer>> tasks = Arrays.asList(
() -> 1,
() -> 2,
() -> 3
);
List<Future<Integer>> results = executor.invokeAll(tasks);
4、invokeAny(Collection<? extends Callable<T>> tasks)
:提交一组带有返回值的任务,返回第一个成功执行完成的任务的结果。这个方法也会阻塞,直到至少有一个任务完成。
ExecutorService executor = Executors.newFixedThreadPool(5);
List<Callable<Integer>> tasks = Arrays.asList(
() -> 1,
() -> 2,
() -> 3
);
Integer result = executor.invokeAny(tasks);
5、shutdown()
和 shutdownNow()
:shutdown()
方法允许之前提交的任务执行完毕,但阻止新任务的提交。shutdownNow()
方法尝试停止所有正在执行的任务,不再启动队列中等待的任务,并返回等待执行的任务列表。
ExecutorService executor = Executors.newFixedThreadPool(5);
executor.shutdown();
ExecutorService executor = Executors.newFixedThreadPool(5);
List<Runnable> remainingTasks = executor.shutdownNow();
6、awaitTermination(long timeout, TimeUnit unit)
:等待所有任务在调用 shutdown()
或 shutdownNow()
后完成执行,或者在超时发生时(以 timeout
和 unit
指定的时间)返回 true
。
ExecutorService executor = Executors.newFixedThreadPool(5);
executor.shutdown();
executor.awaitTermination(10, TimeUnit.SECONDS);
使用 ExecutorService
可以更方便地管理线程池,处理异步任务,以及优雅地控制并发。
二、 Java多线程并行读取多个文件(不考虑性能)
package com.sl.config;
/**
* @package: com.sl.config
* @author: shuliangzhao
* @description:
* @date 2023/11/29 21:39
*/
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.*;
public class ParallelFileReader {
public static void main(String[] args) {
// 文件路径列表
List<String> filePaths = new ArrayList<>();
filePaths.add("D:\aplus\file1.txt");
filePaths.add("D:\aplus\file2.txt");
filePaths.add("D:\aplus\file3.txt");
// 创建线程池
ExecutorService executorService = Executors.newFixedThreadPool(filePaths.size());
// 存储读取结果的 Future 列表
List<Future<List<String>>> futures = new ArrayList<>();
// 提交任务
for (String filePath : filePaths) {
Callable<List<String>> fileReader = () -> readLinesFromFile(filePath);
Future<List<String>> future = executorService.submit(fileReader);
futures.add(future);
}
// 等待所有任务完成
for (Future<List<String>> future : futures) {
try {
List<String> lines = future.get();
// 处理读取的数据
for (String line : lines) {
System.out.println(line);
}
} catch (InterruptedException | ExecutionException e) {
e.printStackTrace();
}
}
// 关闭线程池
executorService.shutdown();
}
// 从文件中读取所有行
private static List<String> readLinesFromFile(String filePath) {
List<String> lines = new ArrayList<>();
try (BufferedReader reader = new BufferedReader(new FileReader(filePath))) {
String line;
while ((line = reader.readLine()) != null) {
lines.add(line);
}
} catch (IOException e) {
e.printStackTrace();
}
return lines;
}
}
在这个例子中,我们有一个包含文件路径的列表 filePaths
,然后创建了一个固定大小的线程池(ExecutorService
),线程池的大小取决于文件的数量。我们使用 ExecutorService
提交了一个读取文件的任务(fileReader
),每个任务都是一个 Callable
,负责读取文件的所有行并返回一个 List<String>
。
以上是一个Java多线程并行读取多个文件简单例子,下一章我们讲在考虑性能时候如何实现Java多线程并行读取多个文件。
原文地址:https://blog.csdn.net/TreeShu321/article/details/134699809
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.7code.cn/show_10805.html
如若内容造成侵权/违法违规/事实不符,请联系代码007邮箱:suwngjj01@126.com进行投诉反馈,一经查实,立即删除!