Я занимаюсь разработкой Java-приложения, которое в течение большей части времени, включая точку выключения, сталкивается с потоком входящих асинхронных вызовов из внешней среды. Во время нормальной работы эти входящие вызовы затем необходимо отправлять в другую среду, опять же асинхронно.
В данный момент мой модуль является «хорошим» гражданином и выполняет некоторую блокировку вокруг флага отключения, который после установки изящно прекратит отправку любых дальнейших исходящих вызовов.
Беспокойство вызывает то, что из-за того, что и входящие, и исходящие вызовы являются асинхронными, мне приходится заставлять каждую «рабочую» задачу выполнять два набора блокировок (см. Ниже), чтобы выполнить одинаковую проверку флага отключения ( EDIT *) 1006 *: Мне было указано в другом вопросе, что для использования семафоров требуется только один сбор / выпуск для каждого работника). Это работает, но есть много таких рабочих задач, и я беспокоюсь о совокупном снижении производительности. Профилирование появится в ближайшее время, когда структура будет немного расширена, но независимо от результата было бы хорошо следовать передовым методам.
Альтернативой является просто не делать блокировку с проверкой флага выключения и обрабатывать ожидаемые исключения, которые генерируются, когда внешние платформы отключаются до завершения обработки асинхронных вызовов. Я должен добавить, что при использовании этого подхода не будет пагубных эксплуатационных последствий. Оба метода приведут к чистому отключению.
Ваши идеи о том, какая практика лучше, пожалуйста? Тяжелая блокировка без исключений, в отличие от блокировки, но без исключения.
С блокировками код рабочего задания выглядит примерно так:
final private ReentrantReadWriteLock shutdownLock = new ReentrantReadWriteLock();
private boolean isShutdown;
private void workerTask()
{
try
{
shutdownLock.readLock().lock();
if (isShutdown)
return;
executeAsynchronously(new Runnable()
{
@Override
final public void run()
{
try
{
shutdownLock.readLock().lock();
if (isShutdown)
return;
// Do something here.
}
finally
{
shutdownLock.readLock().unlock();
}
}
});
}
finally
{
shutdownLock.readLock().unlock();
}
}
Метод shutdown запрашивает shutdownLock.writeLock (), затем устанавливает флаг isShutdown.
Альтернатива без блокировки и ожидания исключений, генерируемых выключением, выглядит примерно так:
volatile private boolean isShutdown;
private void workerTask()
{
try
{
executeAsynchronously(new Runnable()
{
@Override
final public void run()
{
try
{
// Do something here.
}
catch (final FrameworkRuntimeException exception)
{
if ((! isShutdown) || (exception.type !=
FrameworkRuntimeException.FrameworkIsDisposed))
throw exception;
}
}
});
}
catch (final FrameworkRuntimeException exception)
{
if ((! isShutdown) || (exception.type !=
FrameworkRuntimeException.FrameworkIsDisposed))
throw exception;
}
}
Метод shutdown для этой реализации устанавливает для флага volatile isShutdown значение true.
Заранее спасибо за любые отзывы,
Russ
РЕДАКТИРОВАТЬ: Мне было полезно указать в другом вопросе, что я мог бы использовать семафор, чтобы избежать двойной блокировки в первом подходе, так что это не было бы так жестко, в конце концов, но вопрос все еще стоит.