如何通过多线程java编程最大限度地利用资源(RAM和CPU)



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

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.5GB最大堆空间限制的解决方法的反馈。注意,Callable<长>任务并行得令人尴尬。

我曾想过创建一个DOS蝙蝠文件来迭代我的输入文件,然后简单地调用

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

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

任何帮助都将不胜感激。

选项:

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

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

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

查看api文档了解更多信息

最新更新