Reputation: 7244
I have an tomcat webapp where I use a java executor to execute some runnables.
First I allocate the executor service from my executor instance like this:
executorService = Executors.newFixedThreadPool(nThreads, new MyThreadFactory(threadFactoryName))
Then, I launch task using the executor service:
executorService.execute(new MyRunnable);
Then, it seems to work. But my problem is, I am chasing some sort of leak where I get this error after a while of running the server:
Caused by: java.lang.OutOfMemoryError: unable to create new native thread
at java.lang.Thread.start0(Native Method)
at java.lang.Thread.start(Thread.java:640)
at java.util.concurrent.ThreadPoolExecutor.addIfUnderCorePoolSize(ThreadPoolExecutor.java:703)
at java.util.concurrent.ThreadPoolExecutor.execute(ThreadPoolExecutor.java:652)
at something.server.ThreadExecutor.execute(MyRunnable.java:91)
I used the java VisualVM on tomcat instance to trace the thread allocation. I see that when I call 'newFixedThreadPool' I see 'nThreads' new threads. But after their job is done, I see the state of the threads to be on 'wait'.
Is that normal? I don't believe it is, I know the runnables finish their job but the executor service never frees the threads. What can I do to free them, or am I completely out of scope?
Upvotes: 1
Views: 4623
Reputation: 719346
Is that normal? I don't believe it is, I know the runnables finish their job but the executor service never frees the threads.
Yes it is normal. Indeed, this behaviour is desirable because creating a new thread is an expensive operation. The pool threads (or at least the 'core' pool threads) will continue to exist until the executor gets shut down.
What can I do to free them, or am I completely out of scope?
You should be able to configure your thread pool to have a smaller 'core' thread pool, and/or a smaller keepAlive time. Refer to the javadoc for details.
[M]y problem is, I am chasing some sort of leak where I get this error after a while of running the server:
That OOME is not necessarily an indication of a leak. It could be a sign that you haven't left enough non-heap memory for the number of threads that you are trying to create. (Or to put it another way, that your thread pool is too big.)
Upvotes: 2
Reputation: 11977
I think you are instantiating a new ExecutorService
for every request, or something like that.
You should either instantiate only one ExecutorService
, and reuse it, or call shutdown()
on the service after you have finished submitting tasks. The shutdown
function will wait for the tasks to finish, and then free the threads.
Upvotes: 4
Reputation: 22514
You are instantiating a fixed thread pool. The ExecutorService
is not going to release the threads until you terminate the ExecutorService
itself by calling ExecutorService.shutdown()
or ExecutorService.shutdownNow()
.
Upvotes: 2