当前位置: 首页 > 面试题库 >

高吞吐量(3GB / s)文件系统可用时,如何使用Java中的多个线程读取文件

景育
2023-03-14
问题内容

我了解对于普通的主轴驱动器系统,使用多个线程读取文件效率很低。

这是另一种情况,我有一个高吞吐量的文件系统可供使用,它具有196个CPU内核和2TB RAM的读取速度高达3GB / s。

单线程Java程序以最大85-100 MB /s的速度读取文件,因此我有可能变得比单线程更好。我必须读取最大1TB的文件,并且有足够的RAM来加载它。

当前,我使用以下内容或类似内容,但需要使用多线程编写内容以获得更好的吞吐量:

Java 7文件:50 MB / s

List<String> lines = Files.readAllLines(Paths.get(path), encoding);

Java Commons-io:48 MB /秒

List<String> lines = FileUtils.readLines(new File("/path/to/file.txt"), "utf-8");

与番石榴相同:45 MB / s

List<String> lines = Files.readLines(new File("/path/to/file.txt"), Charset.forName("utf-8"));

Java扫描程序类:非常慢

Scanner s = new Scanner(new File("filepath"));
ArrayList<String> list = new ArrayList<String>();
while (s.hasNext()){
    list.add(s.next());
}
s.close();

我希望能够以正确的排序顺序尽快加载文件并构建相同的ArrayList。


问题答案:

这是读取具有多个线程的单个文件的解决方案

_将文件分为N个块,读取线程中的每个块,然后按顺序合并它们。当心跨越块边界的线。这是用户[偷偷]建议的基本思想

下面是对单个20 GB文件的多线程实施的基准测试:

1个线程:50秒:400 MB / s

2个线程:30秒:666 MB / s

4个线程:20秒:1GB / s

8个线程:60秒:333 MB / s

等效的Java7 readAllLines():400秒:50 MB / s

注意:这仅适用于旨在支持高吞吐量I / O的系统,不适用于普通的个人计算机

package filereadtests;

import java.io.*;
import static java.lang.Math.toIntExact;
import java.nio.*;
import java.nio.channels.*;
import java.nio.charset.Charset;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class FileRead implements Runnable
{

private FileChannel _channel;
private long _startLocation;
private int _size;
int _sequence_number;

public FileRead(long loc, int size, FileChannel chnl, int sequence)
{
    _startLocation = loc;
    _size = size;
    _channel = chnl;
    _sequence_number = sequence;
}

@Override
public void run()
{
    try
    {
        System.out.println("Reading the channel: " + _startLocation + ":" + _size);

        //allocate memory
        ByteBuffer buff = ByteBuffer.allocate(_size);

        //Read file chunk to RAM
        _channel.read(buff, _startLocation);

        //chunk to String
        String string_chunk = new String(buff.array(), Charset.forName("UTF-8"));

        System.out.println("Done Reading the channel: " + _startLocation + ":" + _size);

    } catch (Exception e)
    {
        e.printStackTrace();
    }
}

//args[0] is path to read file
//args[1] is the size of thread pool; Need to try different values to fing sweet spot
public static void main(String[] args) throws Exception
{
    FileInputStream fileInputStream = new FileInputStream(args[0]);
    FileChannel channel = fileInputStream.getChannel();
    long remaining_size = channel.size(); //get the total number of bytes in the file
    long chunk_size = remaining_size / Integer.parseInt(args[1]); //file_size/threads

    //Max allocation size allowed is ~2GB
    if (chunk_size > (Integer.MAX_VALUE - 5))
    {
        chunk_size = (Integer.MAX_VALUE - 5);
    }

    //thread pool
    ExecutorService executor = Executors.newFixedThreadPool(Integer.parseInt(args[1]));

    long start_loc = 0;//file pointer
    int i = 0; //loop counter
    while (remaining_size >= chunk_size)
    {
        //launches a new thread
        executor.execute(new FileRead(start_loc, toIntExact(chunk_size), channel, i));
        remaining_size = remaining_size - chunk_size;
        start_loc = start_loc + chunk_size;
        i++;
    }

    //load the last remaining piece
    executor.execute(new FileRead(start_loc, toIntExact(remaining_size), channel, i));

    //Tear Down
    executor.shutdown();

    //Wait for all threads to finish
    while (!executor.isTerminated())
    {
        //wait for infinity time
    }
    System.out.println("Finished all threads");
    fileInputStream.close();
}

}


 类似资料:
  • 我的程序如下: 输入: 提交ID名称薪资部门编号 提交ID1名称1 25100部门1 提交ID2名称2 25200部门2 提交ID3名称3 25300部门3 提交ID4名称4 25400部门4 提交ID5名称5 25500部门5 提交ID6名称6 25600部门6 提交ID7名称7 25700部门7 提交ID8名称8 25800部门8 提交ID9名称9 25900部门9 提交ID10名称10 26

  • 问题内容: 我仍在全神贯注地了解Java中并发的工作方式。我知道(如果您订购的是OO Java 5并发模型)则分别实现a 或with 或or 方法,并且它应该使您尽可能多地并行实现该方法。 但是我仍然不了解Java并发编程的内在知识: 一个是怎样的方法分配给执行工作的同时适量的? 作为一个具体的例子,如果我有一个I / O绑定的方法,该方法将从本地系统上的文件中读取Herman Melville的

  • 面对网络延迟,如何在不牺牲完整性的情况下提高吞吐量?

  • 我需要从很多客户端通过网络套接字连接到java服务器来提取数据。 有很多web套接字实现,我选择了vert。x、 我做了一个简单的演示,在那里我听json的文本帧,用jackson解析它们,然后返回响应。Json解析器对吞吐量没有显著影响。 我的总速度是每秒2.5公里,有2到10个客户。 然后我尝试使用缓冲,客户端不会等待每个响应,而是在服务器确认后发送一批消息(30k-90k),速度提高到每秒8

  • 我使用expo下载了一张图片(a.jpg),代码如下: 文件成功保存在文件系统中。后来当我试图读取文件时,我得到一个错误,文件无法读取。用于读取文件的代码: 上面的代码返回文件无法读取的错误。fileInfo.exists是true,因为文件存在于文件系统中。 读取文件时出错: 如果我尝试读取一个文本文件(a.json),而不是jpg(a.jpg),那么一切都很好。所以,文件系统。readAsSt

  • 我是Jmeter的新手,我有一些无法从Jmeter主页获得的查询。 吞吐量值的确切含义是什么?它是指每个线程每秒没有请求数,还是指线程之间累积没有请求数 我想在125k个请求上平均运行5分钟的测试,假设线程数为60,如何指定吞吐量和延迟值 Jmeter文件中给出的starttime、endtime、duration、delay、rampup period等值是秒/毫秒?如何配置它们 如何在测试期间