Why does ExecutorService keep executing when threads are blocking?

I am trying to write a part of a multithreaded program where each thread from a fixed thread pool tries to fetch an object from a Queue and if the Queue is empty the thread waits.

The problem I am experiencing is that the memory used by the program keeps increasing.

public class Ex3 {

public static LinkedBlockingQueue<Integer> myLBQ = new LinkedBlockingQueue<Integer>(10);

public static void main(String argc[]) throws Exception {
    ExecutorService executor = Executors.newFixedThreadPool(3);
    myLBQ.add(new Integer(1));
    for (;;) {
        executor.execute(new MyHandler(myLBQ));
    }
}
}

class MyHandler implements Runnable {

LinkedBlockingQueue<Integer> myLBQ;

MyHandler(LinkedBlockingQueue<Integer> myLBQ) {
    this.myLBQ = myLBQ;
}

public void run() {
    try {
        myLBQ.take();
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
}
}

I don’t understand why the executor.execute keeps firing when the threads should be waiting for an item to be added to the Queue. How do I modify my code to reflect this?

Answer

This adds tasks to the executor as fast as it can.

for (;;) {
    executor.execute(new MyHandler(myLBQ));
}

This will consume about 200 MB per second. It doesn’t have anything to do with whether there are tasks to perform or not.

If you don’t want to do this I suggest you move the loop to the runnable and add only one. This will cause it to wait for tasks forever.


A better approach is to use the ExecutorService’s builtin queue to queue tasks.

ExecutorService executor = Executors.newFixedThreadPool(3);
final int taskId = 1;
executor.submit(new Runnable() {
    @Override
    public void run() {
        doSomething(taskId);
    }
});

executor.shutdown();

This does the same thing, but is much simpler IMHO.

Leave a Reply

Your email address will not be published. Required fields are marked *