【问题标题】:Parallel processing Windows batch file并行处理 Windows 批处理文件
【发布时间】:2014-09-17 09:09:44
【问题描述】:

我有大量文件需要转换为不同的格式。转换是通过将文件名作为参数的 Java-JAR-File 完成的。我现在有一个 Windows 批处理文件,它使用 for 循环遍历所有文件(有一个文件包含需要转换的所有文件的列表)

for /F %%i in (all_files.txt) do call java -cp %Classpath% de.xyz.Convert -xml %%i .\xml

现在我要执行此操作的机器有八个内核。文件数量约为 360.000,我希望它花费尽可能少的时间,所以我想使用尽可能多的内核。我将如何尽可能简单地使用多个内核? Windows 会自己做吗?

【问题讨论】:

  • 当然允许这由单个 JVM 管理会减少开销。修改您的 jar 以获取输入目录并将该目录中的所有文件处理到输出目录中,然后允许它是多线程的。 :) - 我认为您的问题可能是磁盘读取速度。
  • 很遗憾,我无法修改 jar 文件,它是“专有的”。 ://
  • 好吧,也许我可以做很多逆向工程,但我真的没有时间去做。
  • 鉴于您可以使用 jar,我会考虑为其创建一个可运行的包装器,无需专门修改 jar,只需将其用作库即可。我只是不喜欢一次生成 360,000 个 JVM 实例的想法......
  • 你有一个简单的例子来说明在这种情况下你将如何做到这一点?将 JAR 文件用作单独 Java 应用程序中的库,然后创建运行 de.xyz.Convert 程序的线程?

标签: java windows parallel-processing batch-processing


【解决方案1】:

好的,因为我之前实际上没有做过,所以我把它敲了起来。这不是很好,我使用的 lib 是我创建的一个 jar,它会在 2 分钟后崩溃。希望您能够根据您的需要对其进行逆向工程。

package test;

import java.io.IOException;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;


public class Test {
    public static void main(String[] args) throws InterruptedException, IOException {
        BlockingQueue<Runnable> runnableQueue = new LinkedBlockingQueue<>();
        ExecutorService executorServ = new ThreadPoolExecutor(8, 8, 1, TimeUnit.MINUTES, runnableQueue);
        runnableQueue.add(new RunCrash("Example")); // Add one for each file...
        executorServ.shutdown();
        while(!executorServ.isTerminated()) {
            // running
        }
    }
}

class RunCrash implements Runnable {

    private String fileName;
    RunCrash(String fileName) {
        this.fileName = fileName;
    }

    @Override
    public void run() {
        System.out.println(fileName);
        try {
            crash.CrashMe.main(new String[]{fileName});
        } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }
}

哦,你可以让主线程在其他线程完成之前死掉,我相信JVM会保留执行器和关联的队列。 :)

【讨论】:

  • 谢谢。这是一个很好的起点。让主线程死掉你的意思是我可以删除while循环?目前,我在只添加一个线程后正在努力解决 runnableQueue 已满的问题。我想我得读点书了:)
  • 是的,您可以删除 while 循环。呃...尝试使用 LinkedBlockingQueue 而不是 SynchronousQueue...这应该允许您一次将多个 Runnable 排队...(对不起,我有点匆忙并且没有检查所有 api 的相关性。)
  • 没问题!我发现了一个不同的例子,他们正在使用 ExecutorService executorService = Executors.newFixedThreadPool(nThreads);,我现在也在使用它。然后我 executorService.execute(new Converter(fileName)) 可能会起作用。不幸的是,JAR 文件现在似乎需要一些 apache 类,我想我必须自己添加作为外部库或其他东西......当我开始工作时我会报告:)
  • 好的,我让它工作了。我将线程程序与一个包含 40 个文件的简单 for 循环进行了比较。线程程序需要 83 秒才能完成,简单循环需要 85 秒。不知道为什么没有更多的区别。可能做错了什么,但也许没有太大区别。我这台机器只有四个核心,我们将看看它在 8 核心机器上是如何工作的。如果我计算正确,85 秒内的 40 个文件如果转换意味着超过 200 小时...:/
  • 再次运行,现在这 40 个文件在 86 秒内用这两种方法转换。估计差别不大。不知道为什么。也许 JVM 必须做的“线程管理”花费的时间与多线程操作节省的时间一样多。或者也许以某种方式调用 JAR lib 中的转换方法的 for 循环也会以某种方式产生线程?有任何想法吗?也许在 360k 文件的过程中会有一些节省。
猜你喜欢
  • 2012-07-28
  • 2012-12-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-12-03
  • 1970-01-01
  • 2014-11-15
  • 1970-01-01
相关资源
最近更新 更多