Странная проблема с Java при прерывании цикла - PullRequest
2 голосов
/ 13 марта 2011

У меня есть фрагмент кода, который выглядит следующим образом:

Algorithm a = null;  
while(a == null)  
{  
    a = grid.getAlgorithm();  
}  

getAlgorithm () в моем классе Grid возвращает некоторый подтип алгоритма в зависимости от того, что пользователь выбирает из некоторых параметров.

Моя проблема в том, что даже после выбора алгоритма цикл никогда не завершается.Тем не менее, это не самый сложный момент, если я просто размещу System.out.println («Got here»);после моего вызова getAlgorithm () программа работает отлично и цикл завершается, как и предполагалось.

Мой вопрос: почему добавление этого магического оператора печати внезапно приводит к завершению цикла?

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

Редактировать: рассматриваемая программа НЕ является многопоточной.Код для getAlgorithm ():

public Algorithm getAlgorithm ()  
{  
    return algorithm;  
}

Где алгоритм изначально нулевой, но изменит значение при вводе пользователем.

Ответы [ 5 ]

2 голосов
/ 13 марта 2011

Я считаю, что проблема связана с тем, как выполняется grid.getAlgorithm.Если выполнение метода сопряжено с небольшими затратами, цикл while будет работать очень быстро, пока метод продолжает возвращать ноль.Это часто называют занятое ожидание .

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

1 голос
/ 13 марта 2011

Если этот цикл должен ждать ввода пользователя в GUI, то ой. Плохая, плохая идея и даже с добавлением Thread.sleep() я бы никогда не порекомендовал ее. Вместо этого вы, скорее всего, захотите зарегистрировать прослушиватель событий в рассматриваемом компоненте, и код проверки будет отключаться только при изменении содержимого.

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

1 голос
/ 13 марта 2011

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

0 голосов
/ 14 марта 2011

Существует два сценария:

  1. Ваш код не должен быть многопоточным. В этом случае вам нужно вставить какой-то пользовательский ввод в цикл. В противном случае вы можете оставить его как Algorithm a = grid.getAlgorithm (); и предотвратить бесконечный цикл.
  2. Ваш код является многопоточным, и в этом случае у вас возникает проблема с видимостью. Перейдите по ссылке Атомность, видимость и порядок или прочитайте Параллелизм Java на практике , чтобы узнать больше о видимости. По сути, это означает, что без какой-либо синхронизации между потоками зацикливаемый поток может никогда не обнаружить, что значение изменилось из-за оптимизаций, которые может выполнить JVM.

Вы не упомянули какой-либо контекст о том, как выполняется этот код. Если это консольное приложение и вы начали с «основной» функции, вы бы знали, была ли многопоточность. Я предполагаю, что это не тот случай, так как вы говорите, что многопоточности нет. Другой вариант - это приложение Swing, в этом случае вам следует прочитать Многопоточные приложения Swing . Это может быть веб-приложение, в этом случае может применяться аналогичный случай.

В любом случае вы всегда можете отладить приложение, чтобы увидеть, какой поток записывает в переменную «алгоритм», а затем посмотреть, какой поток читает из него.

Надеюсь, это полезно. В любом случае, вы можете найти больше помощи, если вы дадите немного больше контекста в своем вопросе. Специально для вопроса с таким интригующим названием, как «Странная проблема с Java, пока завершается цикл».

0 голосов
/ 13 марта 2011

Вы должны проверить getAlgorithm (), в методе должно быть что-то не так.

...