I am using threads in my Java application to partially get the data (using network calls). I have a method (which is not in a threaded class), which creates a thread pool with given size (10-15 maximum) and uses them for network calls, and I am calling that method several times from a loop.
When I am running this application on a slow machine (3 GB RAM, Pentium-IV), everything works fine, but when I run it on an iMac (32 GB RAM, i7 processor), it is creating too many threads, about 2,500 sometimes and throwing an out-of-memory error.
I suspect that the JVM
is not putting back the completed threads back in to the pool as soon they are finished, hence it's creating new threads.
And even on the iMac
, if I keep Thread.sleep(1000); in the for
loop which I mentioned above everything works fine. Creating about 900 threads though.
Below are the code samples from this application:
public ArrayList<String> getValuesForKeyFromMaps(String key, ArrayList<Meta> locations) throws InterruptedException, ExecutionException {
int threadNum = locations.size(); // 10-15 at max
ExecutorService executor = Executors.newFixedThreadPool(threadNum);
List<FutureTask<ArrayList<String>>> taskList = new ArrayList<FutureTask<ArrayList<String>>>();
for(final Meta location : locations){
FutureTask<ArrayList<String>> futureTask_1 = new FutureTask<ArrayList<String>>(new Callable<ArrayList<String>>() {
public ArrayList<String> call() throws Exception {
// Service call
return getValues(key, location);
}
});
taskList.add(futureTask_1);
executor.execute(futureTask_1);
}
ArrayList<String> values = new ArrayList<String>();
// Wait until all results are available and combine them at the same time
for (int j = 0; j < threadNum; j++) {
FutureTask<ArrayList<String>> futureTask = taskList.get(j);
values.addAll(futureTask.get());
}
executor.shutdown();
return values;
}
If I call the above method using below for loop on iMac, it throws a memory error, since it's creating about 2,500 threads. But it works fine on the slower machine.
for(String key : keySet){
getValuesForKeyFromMaps(key, metaMap.get(key));
}
And, with the below code, on iMac
it's working fine with about 900 threads.
for(String key : keySet) {
getValuesForKeyFromMaps(key, metaMap.get(key));
Thread.sleep(200); // Sleeping for 200 ms
}
If I increase sleep time in the above for loop to 1000 ms,
it's creating only 30-50 threads and the application is working fine.
How do I control maximum threads allowed in my application? I am intending to create/use 10-15 threads at the maximum at a given time, but Java is creating too many.
locations.size()
. Then you iterate through this locations collection and create one task per location, adding that to the thread pool. Either this locations size is much more than you thought, or you are only creating 10-15 (max) tasks. And ... by the way ... create the thread pool outside of this code snippet. – Partlow