2014-12-30 2 views
7

I love Java 8 потоков. Они интуитивные, мощные и элегантные. Но у них есть один серьезный недостаток ИМО: они делают отладку намного сложнее (если вы не можете решить свою проблему, просто отлаживая лямбда-выражения, на которые отвечает here).Проблемы с использованием интерактивных отладчиков с потоками Java 8

Рассмотрим следующие два эквивалентных фрагментов:

int smallElementBitCount = intList.stream() 
    .filter(n -> n < 50) 
    .mapToInt(Integer::bitCount) 
    .sum(); 

и

int smallElementBitCount = 0; 
for (int n: intList) { 
    if (n < 50) { 
     smallElementBitCount += Integer.bitCount(n); 
    } 
} 

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

В традиционном итеративном стиле вы устанавливаете точку останова на линии totalBitCount += Integer.bitCount(n); и переходите через каждое значение в списке. Вы можете видеть, что представляет собой текущий элемент списка (смотреть n), текущую общую сумму (watch totalBitCount) и, в зависимости от отладчика, каково возвращаемое значение Integer.bitCount.

В новом стиле потока все это невозможно. Вы можете поставить точку останова на весь оператор и перейти к методу sum. Но в целом это почти бесполезно. В этой ситуации в моем тесте мой стек вызовов был 11 глубиной, из которых 10 были java.util-методами, в которых я не интересовался. Невозможно выполнить предикаты тестирования кода или выполнить сопоставление.

В ответах Debugging streams question отмечается, что итеративные отладчики работают достаточно хорошо для разрыва внутри лямбда-выражений (таких как предикат n < 50). Но во многих ситуациях наиболее подходящая точка останова находится не в лямбда.

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

Я пробовал это на NetBeans и Eclipse, и у обоих, похоже, есть те же проблемы.

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

Конечно, есть лучший способ.

В частности, я хотел бы знать:

  • имеют другие испытали этот же вопрос?
  • Есть ли доступные интерактивные отладчики с потоком?
  • Есть ли лучшие методы для отладки этого стиля кода?
  • - это причина ограничить использование потоков в простых случаях?

Любые методы, которые вы нашли успешными, будут высоко оценены.

+0

Это было отмечено как дубликат, но в самом вопросе я ссылаюсь на другой вопрос и объясняю, что я прошу что-то другое - я специально не хочу ломаться внутри выражения лямбды. Я постараюсь сделать это более ясным в вопросе. – sprinter

+0

Извинения - вновь открыт. Надзор на моем конце. –

+0

Этот вопрос подходит к трем из пяти доступных причин, но я не могу заставить себя VTC его. Кажется, это слишком важно. –

ответ

2

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

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

+0

То же самое, к сожалению. – afk5min

Смежные вопросы