Java关于100个并行线程,内存管理。

9
我正在编写一个优化算法,它会创建大约100个线程。目前,我使用for循环一次性启动它们,并告诉每个线程应该join()。
我的问题是每个线程使用的内存都太多了,因此堆空间异常不久就会出现。我想要一种调度方法,但不知道如何实现。
我有这样的想法:启动10个线程,每当其中一个完成时,启动一个新的线程。这样始终保持10个线程在同时运行,直到没有线程为止。
有人有想法或知道如何实现吗?
非常感谢您,来自科隆的问候
Marco

3
如果您对Java和并发编程感兴趣,我强烈推荐这本书:http://www.javaconcurrencyinpractice.com/。 - Mark Pope
4个回答

19

4

这里有一个例子帮助你入门。首先,你需要导入以下内容:

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;

然后你需要在你的方法中放置以下内容:

    ExecutorService pool = Executors.newFixedThreadPool(10);
    for(final Task task: tasks) { 
        pool.execute(new Runnable() {
            @Override
            public void run() {
                task.execute();
            }
        });
    }
    pool.shutdown();
    while(!pool.awaitTermination(1, TimeUnit.SECONDS)) {
        System.out.println("Waiting for tasks to shutdown");
    }

关于上面的一些注释:

  • 您需要实现自己的Task类来实际实现您的算法
  • 任务类不仅仅需要具有execute方法(实际上,如果它具有该签名,您可以让任务实现Runnable并避免匿名内部类)
  • 您需要确保您使用的所有内容都被正确同步。如果您需要更新共享状态(例如,如果您想要计算已处理的任务数量),则java.util.concurrent.atomic中的类非常好。
  • 通常,您只需要执行与机器上的核心/ CPU数量相同的线程。当线程数减少时,性能通常会提高。通常情况下,只有在任务花费大量时间被阻塞时才使用更多线程。

2

不要开启新的线程来执行新的任务,你最好:

  • 拥有一个需要执行的任务队列(而不是运行线程)
  • 使用较小的线程池(正如Michael所提到的)处理这些任务

由于不必为每个任务启动和停止线程,速度和内存上的差异是巨大的。

Java.util.concurrent包详细解释了这一切。 不过,读书可能更容易理解:-(


1

考虑您将要使用的机器的核心数量。如果您通常运行的线程数等于核心数,则性能最佳。正如KLE所说,使用线程池。


我目前每次运行两个,因为我的处理器是英特尔的Core2Duo。性能看起来不错... - Marco
4
如果完全受限于 CPU,这可能是正确的,但如果存在任何阻塞操作(例如 IO、睡眠或某些类型的锁定),那么通常需要更多线程而不是核心,以便保持核心的完全利用。 - mikera

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接