0

我的代码在具有 128 GB RAM 和 64 个内核的 Windows 2008 Server(64 位)上的 32 位 JVM(JRE v1.6)上运行。但是,我可以指定的最大堆空间是 1.5 GB。我的代码如下所示。

int numThreads = Runtime.getRuntime.availableProcessors();
List<Callable<Long>> tasks = new ArrayList<Callable<Long>>();
File dir = new File("/path/to/data");
File[] dataFiles = dir.listFiles();
for(File dataFile : dataFiles) {
 MyTask task = new MyTask(dataFile);
 tasks.add(task);
}
ExecutorService executor = Executors.newFixedThreadPoll(numThreads);
List<Future<Long>> results = executor.invokeAll(tasks);
long total = 0L;
for(Future<Long> result : results) {
 total += result.get();
}
System.out.println("total = " + total);
executor.shutdown();

此代码引发 OutOfMemoryError。我所做的是将线程数更改为更小。

int numThreads = Runtime.getRuntime.availableProcessors();
if(numThreads < 1 || numThreads > 4) {
 numThreads = 4;
}

这个修改后的代码还没有抛出 OutOfMemoryError,但是,这让我很失望,因为有很多资源(RAM 和 CPU 资源)没有被使用。如何在我的环境中最大限度地利用资源?

最重要的是,我想要一些关于 1.5 GB 最大堆空间限制的解决方法的反馈。请注意, Callable<Long> 任务是令人尴尬的并行。

我考虑过创建一个 DOS bat 文件来遍历我的输入文件,然后简单地调用

java -cp %CP% -Xms1024m -Xmx1536m net.analysis.MyProg %1

但这似乎有点古怪/笨拙(现在我必须在 DOS bat 中有逻辑来确定要创建多少个进程,并在生成新进程之前等待这些进程完成)。

任何帮助表示赞赏。

4

3 回答 3

3

32 位 JVM 的最大堆空间约为 1.5GB。当然,您必须切换到在 64 位操作系统上运行的 64 位 JVM 才能分配更多。这是 32 位 JVM 使用 32 位地址这一事实的直接结果。64 位 JVM 可以访问的堆空间大约是 32 位 JVM 的 2 到 40 亿倍。

于 2013-08-20T16:34:50.967 回答
3

选项:

  1. 切换到 64 位 JVM。
  2. 运行一大堆 32 位 JVM,每个 JVM 都执行必须完成的工作的子集。
于 2013-08-20T16:54:42.510 回答
0

为什么不考虑 newCachedThreadPool()。我认为它应该非常适合您的要求和约束。IT 创建一个线程池,根据需要创建新线程,但在可用时将重用以前构建的线程。这些池通常会提高执行许多短期异步任务的程序的性能。如果可用,执行调用将重用以前构造的线程。如果没有可用的现有线程,将创建一个新线程并将其添加到池中。六十秒内未使用的线程将被终止并从缓存中删除。因此,闲置时间足够长的池不会消耗任何资源

查看 api 文档以获取更多信息

于 2013-08-20T17:13:09.097 回答