Java: Исключения как поток управления?

Я хотел сказать, что мой предыдущий пост был бесполезным. Вы можете просто установить AutoFlush на true, и вам не придется перебирать всех слушателей. Тем не менее, у меня все еще была сумасшедшая проблема с параллельными потоками, пытающимися очистить регистратор. Мне пришлось создать еще одно логическое значение, которое было установлено в значение true во время копирования очереди и выполнения записей LogEntry, а затем в процедуре сброса мне пришлось проверить это логическое значение, чтобы убедиться, что чего-то еще не было в очереди и что ничего не обрабатывалось. перед возвращением.

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

     public static void FlushLogs()
    {
        int queueCount;
        bool isProcessingLogs;
        while (true)
        {
            //wait for the current iteration to complete
            m_waitingThreadEvent.WaitOne();

            //check to see if we are currently processing logs
            lock (m_isProcessingLogsSync)
            {
                isProcessingLogs = m_isProcessingLogs;
            }

            //check to see if more events were added while the logger was processing the last batch
            lock (m_loggerQueueSync)
            {
                queueCount = m_loggerQueue.Count;
            }                

            if (queueCount == 0 && !isProcessingLogs)
                break;

            //since something is in the queue, reset the signal so we will not keep looping

            Thread.Sleep(400);
        }
    }
10
задан Nick Heiner 10 October 2009 в 16:33
поделиться

4 ответа

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

В частности, в приведенном вами примере вам нужно будет выполнить некоторую базовую проверку входных данных, которые вы предоставляете конструктору StringMatch. Если бы это был метод, который возвращает код ошибки в случае сбоя проверки некоторых основных параметров, вы могли бы избежать предварительной проверки, но это не так.

17
ответ дан 3 December 2019 в 13:56
поделиться

Я проверил это. На современных JVM это практически не влияет на производительность во время выполнения (если вообще). Если вы запускаете с включенной отладкой, то это значительно замедляет работу.

См. Следующие подробности

(я должен также упомянуть, что я все еще считаю это плохой практикой, даже если это не так ». t влияет на производительность. Больше всего это отражает, возможно, плохой дизайн алгоритма, который будет трудно протестировать)

10
ответ дан 3 December 2019 в 13:56
поделиться

Да, это плохая практика, особенно когда у вас есть средства избежать исключения (проверьте длину строки, прежде чем пытаться ее индексировать). Блоки try and catch предназначены для разделения «нормальной» логики на «исключительную» и логику ошибок. В вашем примере вы распространили «нормальную» логику на блок исключений / ошибок (отсутствие совпадения не является исключением). Вы также неправильно используете подстроку , чтобы использовать возникающую ошибку как поток управления.

6
ответ дан 3 December 2019 в 13:56
поделиться

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

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

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

В приложении, над которым я работаю (и оно отличается от образца, который вы применили), исключения используются для сообщения из вызова метода, что данный результат (например, поиск номера учетной записи и не нахождение его) произошел. Это создает спагетти-код на стороне клиента, поскольку вызывающий метод (во время неисключительного события или нормального события варианта использования) выходит из любого кода, который он выполнял перед вызовом, в блок catch. Это повторяется в некоторых очень длинных методах много раз, что делает код очень легко читаемым.

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

На мой взгляд, вы могли бы сделать это, если бы очень ограничили свои блоки try / catch очень ; но я думаю, что это плохая привычка и может привести к коду, который очень легко неверно истолковать, поскольку вызывающий код будет интерпретировать любое выброшенное исключение как сообщение типа 'GOTO' , изменяя ход выполнения программы. Я боюсь, что, хотя этот случай не попадает в эту ловушку, это часто может привести к привычке кодирования, ведущей к кошмару, в котором я живу прямо сейчас.

И этот кошмар неприятен.

6
ответ дан 3 December 2019 в 13:56
поделиться
Другие вопросы по тегам:

Похожие вопросы: