Многопоточность в Spring 5
Я написал статью про wait-notify примитивы. Закончил я на том, что не стоит делать свои велосипеды, а лучше использовать более высокоуровневые абстракции. Давайте посмотрим, как этот вопрос решает Srping 5.
Скачаем исходники Spring и поищем в них использование wait
, notify
.
В spring core я нашел только одно использование wait
в org.springframework.util.ConcurrencyThrottleSupport#beforeAccess
:
protected void beforeAccess() {
if (this.concurrencyLimit == NO_CONCURRENCY) {
throw new IllegalStateException(
"Currently no invocations allowed - concurrency limit set to NO_CONCURRENCY");
}
if (this.concurrencyLimit > 0) {
boolean debug = logger.isDebugEnabled();
synchronized (this.monitor) {
boolean interrupted = false;
while (this.concurrencyCount >= this.concurrencyLimit) {
if (interrupted) {
throw new IllegalStateException("Thread was interrupted while waiting for invocation access, " +
"but concurrency limit still does not allow for entering");
}
if (debug) {
logger.debug("Concurrency count " + this.concurrencyCount +
" has reached limit " + this.concurrencyLimit + " - blocking");
}
try {
this.monitor.wait();
}
catch (InterruptedException ex) {
// Re-interrupt current thread, to allow other threads to react.
Thread.currentThread().interrupt();
interrupted = true;
}
}
if (debug) {
logger.debug("Entering throttle at concurrency count " + this.concurrencyCount);
}
this.concurrencyCount++;
}
}
}
На мой взгляд код прекрасен. Вместо 0
используется NO_CONCURRENCY
. Мелочь, а улучшает читаемость кода.
При этом в выражении this.concurrrencyLimit > 0
константа не используется. И это логично, странно иметь что-то большее отсутствия конкурентности.
Метод beforeAccess
ждет, когда уменьшится concurrencyCount
, это происходит в методе afterAccess
, а потом пропускает поток выполняться.
Выполнение доступа к ресурсу может занимать очень долгое время и не стоит полить переменную зря.
Сейчас хорошо бы рассмотреть другой throttler, например из Guava, но я это сделаю в другой раз.