详解Java多线程并行读取多个文件(一)

目录

一、ExecutorService

二、 Java多线程并行读取多个文件(不考虑性能)


在 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() 后完成执行,或者在超时发生时(以 timeoutunit 指定的时间)返回 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多线程并行读取多个文件。

  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
`newFixedThreadPool` 是 Java 中线程池的一种实现方式,它可以创建一个固定大小的线程池,并且只有在池中的所有线程都处于忙碌状态时,才会将新的任务加入到队列中等待执行。 以下是 `newFixedThreadPool` 的详细解释: 1. 创建一个固定大小的线程池,该线程池中的线程数量是固定的,一旦创建便无法更改。这意味着,如果池中的所有线程都处于忙碌状态并且有更多的任务需要执行,那么这些任务将会被放置在一个队列中,等待空闲线程的出现。 2. 线程池中的所有线程都是可重用的,这意味着在执行完任务之后,线程将返回线程池并等待下一个任务的到来。 3. 线程池中的所有线程都是后台线程,这意味着它们不会阻止应用程序的关闭。 4. 线程池中的任务可以是任何实现了 `Runnable` 接口或 `Callable` 接口的对象。使用 `Callable` 接口可以允许任务返回一个值,并且可以抛出异常。 5. 线程池中的任务将按照加入队列的顺序进行执行。 6. `newFixedThreadPool` 的底层实现是一个无界的工作队列和一个固定数量的线程池。 使用 `newFixedThreadPool` 可以有效地控制线程的数量,从而避免创建过多的线程而导致系统的资源浪费和性能下降。但是,如果任务的数量过多,而线程池中的线程数量过少,那么仍然会出现任务排队等待的情况。因此,在使用 `newFixedThreadPool` 时,需要根据实际情况来确定线程池的大小。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

境里婆娑

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值