qwera
qwera

Reputation: 185

Spawning tons of threads without running out of memory

I have a multi-threaded application which creates hundreds of threads on the fly. When the JVM has less memory available than necessary to create the next Thread, it's unable to create more threads. Every thread lives for 1-3 minutes. Is there a way, if I create a thread and don't start it, the application can be made to automatically start it when it has resources, and otherwise wait until existing threads die?

Upvotes: 3

Views: 816

Answers (4)

Jeff Goldberg
Jeff Goldberg

Reputation: 961

I ran into a similar issue recently and I used the NotifyingBlockingThreadPoolExecutor solution described at this site:

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

The basic idea is that this NotifyingBlockingThreadPoolExecutor will execute tasks in parallel like the ThreadPoolExecutor, but if you try to add a task and there are no threads available, it will wait. It allowed me to keep the code with the simple "create all the tasks I need as soon as I need them" approach while avoiding huge overhead of waiting tasks instantiated all at once.

It's unclear from your question, but if you're using straight threads instead of Executors and Runnables, you should be learning about java.util.concurrent package and using that instead: http://docs.oracle.com/javase/tutorial/essential/concurrency/executors.html

Upvotes: 2

jayunit100
jayunit100

Reputation: 17648

This is an alternative, lower level solution Then the above mentioed NotifyingBlocking executor - it is probably not as ideal but will be simple to implement

If you want alot of threads on standby, then you ultimately need a mechanism for them to know when its okay to "come to life". This sounds like a case for semaphores.

Make sure that each thread allocates no unnecessary memory before it starts working. Then implement as follows :

1) create n threads on startup of the application, stored in a queue. You can Base this n on the result of Runtime.getMemory(...), rather than hard coding it.

2) also, creat a semaphore with n-k permits. Again, base this onthe amount of memory available.

3) now, have each of n-k threads periodically check if the semaphore has permits, calling Thread.sleep(...) in between checks, for example.

4) if a thread notices a permit, then update the semaphore, and acquire the permit.

If this satisfies your needs, you can go on to manage your threads using a more sophisticated polling or wait/lock mechanism later.

Upvotes: 0

jefflunt
jefflunt

Reputation: 33954

You're responsible for checking your available memory before allocating more resources, if you're running close to your limit. One way to do this is to use the MemoryUsage class, or use one of:

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

...to see how much memory is available. To figure out how much is used, of course, you just subtract total from free. Then, in your app, simply set a MAX_MEMORY_USAGE value that, when your app has used that amount or more memory, it stops creating more threads until the amount of used memory has dropped back below this threshold. This way you're always running with the maximum number of threads, and not exceeding memory available.

Finally, instead of trying to create threads without starting them (because once you've created the Thread object, you're already taking up the memory), simply do one of the following:

  • Keep a queue of things that need to be done, and create a new thread for those things as memory becomes available
  • Use a "thread pool", let's say a max of 128 threads, as all your "workers". When a worker thread is done with a job, it simply checks the pending work queue to see if anything is waiting to be done, and if so, it removes that job from the queue and starts work.

Upvotes: 2

David Schwartz
David Schwartz

Reputation: 182819

Just write code to do exactly what you want. Your question describes a recipe for a solution, just implement that recipe. Also, you should give serious thought to re-architecting. You only need a thread for things you want to do concurrently and you can't usefully do hundreds of things concurrently.

Upvotes: 1

Related Questions