Почему ExecutorService продолжает выполняться, когда потоки блокируются?

Я пытаюсь написать часть многопоточной программы, в которой каждый поток из фиксированного пула потоков пытается получить объект из очереди, и если очередь пуста, поток ждет.

Проблема, с которой я сталкиваюсь, заключается в том, что память, используемая программой, продолжает увеличиваться.

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();
    }
}
}

Я не понимаю, почему executor.execute продолжает срабатывать, когда потоки должны ожидать добавления элемента в очередь. Как мне изменить свой код, чтобы отразить это?


person Mat    schedule 11.07.2011    source источник


Ответы (2)


Это добавляет задачи исполнителю так быстро, как только может.

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

Это будет потреблять около 200 МБ в секунду. Это не имеет никакого отношения к тому, есть задачи для выполнения или нет.

Если вы не хотите этого делать, я предлагаю вам переместить цикл в runnable и добавить только один. Это заставит его ждать задачи вечно.


Лучшим подходом является использование встроенной очереди ExecutorService для постановки задач в очередь.

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

executor.shutdown();

Это делает то же самое, но намного проще ИМХО.

person Peter Lawrey    schedule 11.07.2011
comment
Спасибо, я не знал, что элементы будут добавлены в очередь независимо от того, доступны ли потоки для их выполнения. - person Mat; 11.07.2011
comment
Вы можете изменить его так, чтобы он отклонял задачи и не было ожидающего потока, но обычно это приводит к RejectedExecutionException, что вам здесь тоже не нужно. - person Peter Lawrey; 11.07.2011

это потому, что вы создаете миллионы экземпляров MyHandler и вставляете их во внутреннюю очередь исполнителя.

Этот бесконечный цикл for довольно подлый.

person Augusto    schedule 11.07.2011