产生大量线程而不会耗尽内存

时间:2011-12-20 02:17:38

标签: java multithreading memory-management

我有一个多线程应用程序,可以动态创建数百个线程。当JVM的可用内存少于创建下一个Thread所需的内存时,它无法创建更多线程。每个线程持续1-3分钟。有没有办法,如果我创建一个线程并且不启动它,可以使应用程序在有资源时自动启动它,否则等到现有线程死掉?

4 个答案:

答案 0 :(得分:2)

如果您的运行接近极限,则在分配更多资源之前,您有责任检查可用内存。一种方法是使用MemoryUsage类,或使用以下之一:

Runtime.getRuntime().totalMemory()
Runtime.getRuntime().freeMemory()

...看看有多少内存可用。要弄清楚使用了多少,当然,您只需从total中减去free。然后,在您的应用中,只需设置一个MAX_MEMORY_USAGE值,当您的应用使用该数量或更多内存时,它会停止创建更多线程,直到已用内存< / strong>已经回落到此阈值以下。这样,您始终以最大线程数运行,并且不会超出可用内存。

最后,不要尝试创建线程而不启动它们(因为一旦你创建了Thread对象,你就已经占用了内存),只需执行以下操作之一:

  • 保留需要完成的事情的队列,并在内存可用时为这些事情创建新线程
  • 使用“线程池”,假设最多128个线程,就像所有“工作者”一样。当一个工作线程完成一个作业时,它只是检查待处理的工作队列以查看是否有任何事情要等待完成,如果有,它会从队列中删除该作业并开始工作。

答案 1 :(得分:2)

我最近遇到了类似的问题,我使用了本网站所描述的NotifyingBlockingThreadPoolExecutor解决方案:

http://today.java.net/pub/a/today/2008/10/23/creating-a-notifying-blocking-thread-pool-executor.html

基本思想是这个NotifyingBlockingThreadPoolExecutor将像ThreadPoolExecutor一样并行执行任务,但是如果你尝试添加任务并且没有可用的线程,它将等待。它允许我使用简单的“在我需要时创建我需要的所有任务”方法来保持代码,同时避免一次性实例化等待任务的巨大开销。

您的问题不清楚,但如果您使用的是直线而不是Executors和Runnables,那么您应该了解java.util.concurrent包并使用它代替:http://docs.oracle.com/javase/tutorial/essential/concurrency/executors.html

答案 2 :(得分:1)

只需编写代码即可完全按照您的意愿执行操作。您的问题描述了解决方案的配方,只需实现该配方。此外,你应该认真考虑重新架构。你只需要一个线程来处理你想要做的事情并发,你就不能同时做好数百件事。

答案 3 :(得分:0)

这是一个替代的,较低级别的解决方案然后上面的mentioed NotifyingBlocking执行器 - 它可能不是那么理想,但实现起来很简单

如果你想要很多线程处于待机状态,那么你最终需要一种机制让他们知道什么时候可以“复活”。这听起来像信号量的情况。

确保每个线程在开始工作之前不分配不必要的内存。然后按如下方式实施:

1)在启动应用程序时创建n个线程,存储在队列中。您可以将此基于Runtime.getMemory(...)的结果,而不是对其进行硬编码。

2)同时,创建一个具有n-k许可证的信号量。再次,基于可用内存量。

3)现在,让每个n-k个线程定期检查信号量是否有许可,例如在两次检查之间调用Thread.sleep(...)。

4)如果一个线程注意到许可证,则更新信号量,并获得许可证。

如果满足您的需求,您可以稍后使用更复杂的轮询或等待/锁定机制来管理您的线程。