Home > Enterprise >  Increasing memory consumption using FixedThreadPool
Increasing memory consumption using FixedThreadPool

Time:02-03

im testing with Executors.newFixedThreadPool() and i am having extremely high memory consumption, the code is the following:

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.*;

public class ExecutorServiceTest {

    public static void main(String[] args) throws ExecutionException, InterruptedException {

        int threadCount = 7;


        ExecutorService executorService = Executors.newFixedThreadPool(threadCount);
        List<Future> futures = new ArrayList<>();
        while (true) {

            for (int i = 0; i < threadCount; i  ) {

                int finalI = i;
                futures.add(executorService.submit(() -> {
                    try {
                        Thread.sleep(8000);
                        return finalI  ;
                    } catch (InterruptedException e) {
                        throw new RuntimeException(e);
                    }

                }));
            }

            for (int i = 0; i < threadCount; i  ) {

                System.out.println("Value: " futures.get(i).get());
            }
//            System.gc();
        }

    }

}

The heap memory goes to like 4GB in a couple of minutes(It nevers goes back down again, left it for hours and it goes until it runs out of memory). If i uncomment the System.gc() line it gets way better, but it still increases, it starts at around 37MB and after approximately 10 minutes it scales up to 49MB and never stops increasing(left it for around 20 minutes and still increasing). I made a heap Dump with visualVM from the test without manually calling GC.

Heap Dump Summary Heap Dump Objects All objects in FutureTasks are 32B, there are more than 50k Also more than 50k of LinkedBlockingQueueNode And also more than 50k of Lambdas

CodePudding user response:

In the first loop you are creating a new Future on every iteration and storing it inside the List:

// adds a new Future instance to the list of futures
futures.add(executorService.submit(() -> {
                

This ever-growing list is consuming your memory.

I don't know what you are trying to achieve exactly, but you can avoid the memoty issue by clearing the list at the end of every iteration of the while-loop, instead of calling GC.

Also you probably don't want to throw a RuntimeException when the Thread is interrupted. Either re-throw the InterruptedException, or re-interrupt the thread as shown below (see this Baeldung article on Thread interruption)

while (true) {

    for (int i = 0; i < threadCount; i  ) {
        int finalI = i;
        futures.add(executorService.submit(() -> {
            try {
                Thread.sleep(8000);
                return finalI  ;
            } catch (InterruptedException e) {
                Thread.currentThread().interrupt();
            }
        }));
    }

    for (int i = 0; i < threadCount; i  ) {
        System.out.println("Value: " futures.get(i).get());
    }

    futures.clear();
}

Alternatively you could use an array of the right length and set the futures by index instead of adding to a list, so you don't have to clear.

Future[] futures = new Future[threadCount];
    // ...
    futures[i] = executorService.submit(() -> {
    // ...
    System.out.println("Value: "   futures[i].get());
  • Related