如何通过多线程java编程最大化资源(RAM和CPU)的使用?

时间:2013-08-20 16:31:55

标签: java multithreading memory-management jvm java.util.concurrent

我的代码在Windows 2008 Server(64位)上的32位JVM(JRE v1.6)上运行,具有128 GB的RAM和64个内核。但是,我可以指定的最大堆空间是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&lt; Long&gt;任务非常平行。

我考虑过创建一个DOS bat文件迭代我的输入文件然后只需调用

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

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

感谢任何帮助。

3 个答案:

答案 0 :(得分:3)

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

答案 1 :(得分:3)

选项:

  1. 切换到64位JVM。
  2. 运行一大堆32位JVM,每个JVM都执行必须完成的工作的子集。

答案 2 :(得分:0)

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

查看api doc以获取更多信息