【问题标题】:Why Java parallel file writing is not working?为什么 Java 并行文件写入不起作用?
【发布时间】:2020-08-12 20:51:27
【问题描述】:

我正在尝试编写一个脚本,该脚本将使用不同的参数运行 .exe 程序 4 次。我为每个 .exe 运行创建了一个线程。每个线程将写入一个输出文件。我的问题是,它应该并行写入,但正如您在下面的屏幕截图中看到的那样,文件一个接一个地写入。应该如何解决?

主要方法如下:

public static void main (String args[]) {
    ExecutorService executor = Executors.newFixedThreadPool(4);
    executor.execute(new RunnableReader("myprogram.exe", param1, outputFile1));
    executor.execute(new RunnableReader("myprogram.exe", param2, outputFile2));
    executor.execute(new RunnableReader("myprogram.exe", param3, outputFile3));
    executor.execute(new RunnableReader("myprogram.exe", param4, outputFile4));
    executor.shutdown();
}

这是可运行的类:

public class RunnableReader implements Runnable {
    private String program;
    private String param;
    String outputFile;

    public RunnableReader(String program, String param, String outputFile) {
        this.program = program;
        this.param = param;
        this.outputFile = outputFile;
    }

    @Override
    public void run() {
        try {
            ProcessBuilder pb = new ProcessBuilder(program, param);
            pb.redirectOutput(ProcessBuilder.Redirect.PIPE);
            pb.redirectErrorStream(true);
            Process proc = pb.start();
            InputStream stream = proc.getInputStream();
            BufferedReader reader = new BufferedReader(new InputStreamReader(stream));
            BufferedWriter writer = new BufferedWriter(new FileWriter(outputFile, true));
            for(String output; (output = reader.readLine()) != null) {
                writer.append(output);
                writer.append("\n");
            }
            writer.close();
            reader.close();
            stream.close();
  
        } catch(IOException e) {
            e.printStackTrace();
        }
    }
}

【问题讨论】:

  • 我在 Java 代码中看不到任何会阻止并行执行的内容。你确定myprogram.exe 可以并行运行吗?也许程序对文件或数据库采取了排他锁。您是否尝试过打开 4 个命令提示符并手动并行执行 4 次?
  • 那,仅仅因为你的时间戳不在同一时刻并不意味着 exe 没有同时运行。他们可能只需要不同的时间来运行。每个文件时间戳之间有很多时间(其中一些是 30 多分钟)。
  • 要了解更多信息,请尝试在 Java 代码中插入打印语句,例如pb.start() 之后的打印语句,表示进程已启动。如果立即打印 4 次,您肯定知道不是 Java 导致了问题。
  • @SnakeDoc “创建日期”(文件打开时间)与另一个文件的“修改日期”(文件关闭时间)完全匹配这一事实强烈表明这 4 个文件是连续创建的。跨度>
  • @Andreas 啊,是的,好点,我在屏幕截图中错过了!那么它必须是外部的东西,比如数据库锁或你提到的东西。

标签: java multithreading threadpool bufferedwriter


【解决方案1】:

我自己无法对此进行测试,也不知道它是否真的会导致执行阻塞。但是,我认为我应该指出,您阅读该过程'InputStream 可能是不必要的。

正如Oracle docs 所述,ProcessBuilder.redirectOutput(ProcessBuilder.Redirect.PIPE) 导致Process.getInputStream() 返回进程的标准输出。

考虑到这一点,您可以摆脱整个for-loop,而只需执行ProcessBuilder.redirectOutput(new File(outputFile)) 之类的操作,这样您的方法就会变成这样

@Override
public void run() {
    try {
        ProcessBuilder pb = new ProcessBuilder(program, param);
        pb.redirectOutput(new File(outputFile));
        pb.redirectErrorStream(true);
        Process proc = pb.start();
    } catch(IOException e) {
        e.printStackTrace();
    }

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-10-01
    • 1970-01-01
    • 2017-10-14
    • 1970-01-01
    相关资源
    最近更新 更多