Как управлять исполнителями

В моей практике нередки случаи, когда разрабатываемое мной программное обеспечение становится большим и сложным, и различные его части используют исполнителей по-своему. С точки зрения производительности было бы лучше использовать разные конфигурации пула потоков в каждой части. Но с точки зрения удобства сопровождения и удобства использования кода было бы предпочтительнее, если бы все, что связано с потоками, параллелизмом и загрузкой ЦП, хранилось и настраивалось в каком-то централизованном месте.

Создание собственного пула потоков для каждого класса, которому требуется параллельное выполнение или планирование, недопустимо, поскольку трудно контролировать их жизненные циклы и общее количество потоков.

Создание некоего типа ExecutorManager и передача одного пула потоков вокруг приложения также недопустимы, поскольку, в зависимости от типа задачи и частоты отправки, неправильно настроенное сочетание рабочей очереди и размера пула потоков может снизить производительность. действительно плохо.

Итак, вопрос: существуют ли какие-то общие подходы к решению этой проблемы?


person Kovalsky    schedule 11.11.2011    source источник
comment
Похоже, ваша настоящая проблема заключается в том, чтобы найти простой способ управления жизненным циклом ваших компонентов. Если у вас есть простой способ управления вашими компонентами и убедитесь, что только минимум из них создает потоки, у вас не должно возникнуть никаких проблем. Если вы не говорите о IO, вам не нужно больше потоков, чем у вас есть ядер.   -  person Peter Lawrey    schedule 11.11.2011


Ответы (2)


Я бы создал 2 или 3 пула потоков, которые можно настроить по-разному в зависимости от задач, которые они выполняют, если есть более 3 разных одновременных действий, у вас есть большая проблема.

Пулы могут быть введены по мере необходимости (например, по имени), кроме того, я бы создал аннотацию для выполнения определенного метода с определенным пулом/исполнителем с использованием АОП (например, aspectj).

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

Например:

@Concurrent ("pool1")
public void taskOfTypeOne() {
}

@Concurrent ("pool2")
public void taskOfTypeTwo() {
}
person azl    schedule 04.12.2012
comment
Спасибо! Вот о чем я думал. Я думаю, что буду придерживаться этого подхода, хотя ответ Spring также действителен :-) - person Kovalsky; 10.12.2012

То, что вам нужно, — это Внедрение зависимостей или Инверсия управления. Одна из самых популярных сред внедрения зависимостей для Java — Весна. Вы создаете обычные объекты Java, но либо с определенными аннотациями, либо путем их настройки в XML, чтобы связать их вместе. Таким образом, вы можете настроить разные экземпляры ExecutorService в одном месте и запросить их внедрение (возможно, по имени) в клиентские классы, которым они нужны.

person Tom G    schedule 04.12.2012
comment
Да, хотя я еще недостаточно глубоко изучил Spring, кажется, что он поддерживает меня почти по всем пунктам. Только нужно некоторое время, чтобы ознакомиться и настроить все и вся, поэтому мне было интересно, есть ли варианты. - person Kovalsky; 10.12.2012