Java 并行文件处理

标签 java multithreading file-handling

我有以下代码:

import java.io.*;
import java.util.concurrent.* ;
public class Example{
public static void main(String args[]) {
    try {
        FileOutputStream fos = new FileOutputStream("1.dat");
        DataOutputStream dos = new DataOutputStream(fos);

        for (int i = 0; i < 200000; i++) {
            dos.writeInt(i);
        }
        dos.close();                                                         // Two sample files created

        FileOutputStream fos1 = new FileOutputStream("2.dat");
        DataOutputStream dos1 = new DataOutputStream(fos1);

        for (int i = 200000; i < 400000; i++) {
            dos1.writeInt(i);
        }
        dos1.close();

        Exampless.createArray(200000); //Create a shared array
        Exampless ex1 = new Exampless("1.dat");
        Exampless ex2 = new Exampless("2.dat");
        ExecutorService executor = Executors.newFixedThreadPool(2); //Exexuted parallaly to cont number of matches in two file
        long startTime = System.nanoTime();
        long endTime;
        Future<Integer> future1 = executor.submit(ex1);
        Future<Integer> future2 = executor.submit(ex2);
        int count1 = future1.get();
        int count2 = future2.get();
        endTime = System.nanoTime();
        long duration = endTime - startTime;
        System.out.println("duration with threads:"+duration);
        executor.shutdown();
        System.out.println("Matches: " + (count1 + count2));

        startTime = System.nanoTime();
        ex1.call();
        ex2.call();
        endTime = System.nanoTime();
        duration = endTime - startTime;
        System.out.println("duration without threads:"+duration);

    } catch (Exception e) {
        System.err.println("Error: " + e.getMessage());
    }
}
}

class Exampless implements Callable {

public static int[] arr = new int[20000];
public String _name;

public Exampless(String name) {
    this._name = name;
}

static void createArray(int z) {
    for (int i = z; i < z + 20000; i++) { //shared array
        arr[i - z] = i;
    }
}

public Object call() {
    try {
        int cnt = 0;
        FileInputStream fin = new FileInputStream(_name);
        DataInputStream din = new DataInputStream(fin);      // read file and calculate number of matches
        for (int i = 0; i < 20000; i++) {
            int c = din.readInt();
            if (c == arr[i]) {
                cnt++;
            }
        }
        return cnt ;
    } catch (Exception e) {
        System.err.println("Error: " + e.getMessage());
    }
    return -1 ;
}

}

我正在尝试计算具有两个文件的数组中的匹配项数。现在,虽然我在两个线程上运行它,但代码运行不佳,因为:

(单线程运行,文件 1 + 文件 2 读取时间)<(文件 1 || 文件 2 多线程读取时间)。

谁能帮我解决这个问题(我有 2 个核心 CPU,文件大小约为 1.5 GB)。

最佳答案

在第一种情况下,您正在按顺序读取一个文件,逐字节,逐 block 。这与磁盘 I/O 一样快,前提是文件不是很碎片化。当您完成第一个文件后,磁盘/操作系统会找到第二个文件的开头,并继续非常高效地线性读取磁盘。

在第二种情况下,您不断地在第一个和第二个文件之间切换,迫使磁盘从一个地方寻找到另一个地方。这个额外的搜索时间(大约 10 毫秒)是您混淆的根源。

哦,你知道磁盘访问是单线程的,而你的任务是 I/O 绑定(bind)的,所以只要你从同一个物理磁盘读取,就没有办法将这个任务拆分为多个线程会有帮助吗?只有在以下情况下,您的方法才是合理的:

  • 除了读取文件外,每个线程还执行一些 CPU 密集型或阻塞操作,与 I/O 相比慢了一个数量级。

  • 文件在不同的物理驱动器上(不同的分区是不够的)或在某些 RAID 配置上

  • 您正在使用 SSD 驱动器

关于Java 并行文件处理,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11744730/

相关文章:

java - 使用 Java 和 Dynamic C 通过 WiFi 进行套接字连接

c# - WPF BitmapFrame 和多线程

python - 给定比例将文件随机分发到训练/测试中

python - 编写和编辑文件 (Python)

java - 脚本应该等到浏览器手动关闭

java - 求数组中组合的总数?

java - 为什么 Apache Beam 2.2 写入 GCS 失败?

multithreading - 如何在线程之间可变地共享 i32?

Android volatile 不工作?

python - 在 Python3 中解密后无法从加密文件中恢复原始图像文件