Если поток прерван в то время как внутри Object.wait()
или Thread.join()
, это бросает InterruptedException
, который сбрасывает прерванное состояние потока. Т.е., если у меня есть цикл как эта внутренняя часть a Runnable.run()
:
while (!this._workerThread.isInterrupted()) {
// do something
try {
synchronized (this) {
this.wait(this._waitPeriod);
}
} catch (InterruptedException e) {
if (!this._isStopping()) {
this._handleFault(e);
}
}
}
поток продолжит бежать за вызовом interrupt()
. Это означает, что я должен явно убежать из цикла путем проверки на мой собственный флаг остановки в условии цикла, повторно бросить исключение или добавить a break
.
Теперь, это не точно проблема, так как это поведение хорошо документируется и не препятствует тому, чтобы я делал что-либо способ, которым я хочу. Однако я, кажется, не понимаю понятия позади него: Почему поток не считают прерванным еще, после того как исключение было выдано? Подобное поведение также происходит, если Вы получаете прерванное состояние с interrupted()
вместо isInterrupted()
, затем также поток будет только казаться прерванным однажды.
Я делаю что-то необычное здесь? Например, это более распространенный для ловли InterruptedException
вне цикла?
(Даже при том, что я не точно новичок, я отметил этого "новичка", потому что это походит на очень простой вопрос мне, смотря на него.)
Идея состоит в том, что прерывание должно обрабатываться один раз. Если явное InterruptedException
не очистило флаг «прерывание», то большинству ловушек для InterruptedException
пришлось бы явно сбросить этот флаг. И наоборот, вы можете «не очистить» флаг самопрерыванием ( Thread.currentThread (). Interrupt ()
). Разработчики Java пошли на семантику, которая в большинстве случаев экономила бы нажатия клавиш (т.е. вам чаще нужно сбросить флаг, чем оставить его установленным).
Напишите свой код таким образом, и вам не понадобится флаг:
try {
while (!this._workerThread.isInterrupted()) {
// do something
synchronized (this) {
this.wait(this._waitPeriod);
}
// do something else
}
} catch (InterruptedException e) {
// ignore ...
}
Как указывает @Boyan, подавлять это исключение прерывания - плохая идея ... в общем. В этом случае контекст будет определять, следует ли вам раздавить его (как указано выше), установить флаг прерывания (снова) или разрешить распространение исключения. Среди прочего, это зависит от того, что означает прерывание в вашем приложении.
Это потому, что InterruptedException
считается ненормальным событием, когда кто-то другой пытается остановить поток извне.
Если вы действительно хотите прервать поток, вы просто нарушаете его условие цикла, задав логическое значение или что-то подобное. Или вы используете .wait ()
и .notify ()
изнутри этого потока . Но если вы выполняете wait ()
извне: