Механизм прерывания потока - предпочтительный способ заставить (взаимодействующий) поток ответить на запрос, чтобы остановить то, что он делает. Любой поток (включая сам поток, я думаю) может вызывать поток interrupt()
.
На практике нормальные варианты использования interrupt()
включают некую структуру или менеджер, говорящий некоторому рабочему потоку, чтобы он остановил то, что они делают. Если рабочий поток «осведомлен о прерываниях», он заметит, что он был прерван через исключение или периодически проверяя свой флаг прерывания. Заметив, что он был прерван, поток с хорошим поведением откажется от того, что он делает, и завершит работу.
Предполагая приведенный выше вариант использования, ваш код, вероятно, будет прерван, если он будет запущен в среде Java или из какого-либо рабочего потока. И когда он прерывается, ваш код должен отказаться от того, что он делает, и заставить себя завершить работу наиболее подходящими способами. В зависимости от того, как был вызван ваш код, это может быть сделано путем возврата или выдачи соответствующего исключения. Но, наверное, не стоит называть System.exit()
. (Ваше приложение не обязательно знает, почему оно было прервано, и уж точно не знает, есть ли другие потоки, которые должны быть прерваны фреймворком.)
С другой стороны, если ваш код не предназначен для работы под управлением какой-либо инфраструктуры, вы можете утверждать, что InterruptedException
это неожиданное исключение; т.е. ошибка. В этом случае вы должны рассматривать исключение, как и другие ошибки; например, оберните его в непроверенное исключение, перехватите и запишите его в тот же момент, когда вы имеете дело с другими непредвиденными непроверенными исключениями. (В качестве альтернативы ваше приложение может просто игнорировать прерывание и продолжать делать то, что делало.)
1) Если я сам никогда не прерываю другие потоки, что может вызвать InterruptedException?
Один из примеров: ваши Runnable
объекты выполняются с использованием ExecutorService
и shutdownNow()
вызываются в службе. Теоретически любой сторонний пул потоков или фреймворк управления потоками может законно делать что-то подобное.
2) Если я никогда не прерываю другие потоки сам с помощью interrupt () ... что значит InterruptedException
тогда? Что мне делать, если я поймаю одного? Закрыть мое приложение?
Вам необходимо проанализировать кодовую базу, чтобы понять, что вызывает interrupt()
звонки и почему. Как только вы это выясните, вы можете решить, что >> должна делать ваша << часть приложения.
Пока вы не знаете, почему InterruptedException
возникает ошибка, я бы посоветовал рассматривать это как серьезную ошибку; например, распечатайте трассировку стека в файл журнала и закройте приложение. (Очевидно, что это не всегда правильный ответ ... но дело в том, что это «ошибка», и на нее необходимо обратить внимание разработчика / сопровождающего.)
3) Как узнать, кто / что звонит interrupt()
?
На это нет хорошего ответа. Лучшее, что я могу предложить, - это установить точку останова на Thread.interrupt()
и посмотреть стек вызовов.
Как указывали другие, прерывание потока (фактически, прерывание блокирующего вызова) обычно используется для целей чистого выхода или отмены текущей активности.
Однако не следует относиться к
InterruptedException
одиночке как к «команде выхода». Вместо этого вы должны думать о прерываниях как о средстве управления текущим статусом потоков, во многом так же, как этоObject.notify()
делается. Точно так же, как вы проверяете текущее состояние после пробуждения от вызоваObject.wait()
(вы не предполагаете, что пробуждение означает, что ваше условие ожидания было выполнено), после того, как вас подтолкнули прерыванием, вы должны проверить, почему вы были прерваны . Обычно есть способ сделать это. Например,java.util.concurrent.FutureTask
естьisCancelled()
метод.Пример кода:
public void run() { .... try { .... // Calls that may block. } catch (InterruptedException e) { if (!running) { // Add preferred synchronization here. return; // Explicit flag says we should stop running. } // We were interrupted, but the flag says we're still running. // It would be wrong to always exit here. The interrupt 'nudge' // could mean something completely different. For example, it // could be that the thread was blocking on a read from a particular // file, and now we should read from a different file. // Interrupt != quit (not necessarily). } .... } public void stop() { running = false; // Add preferred synchronization here. myThread.interrupt(); }
источник
Проблема с вопросом - «Я». «Я» обычно относится к одному экземпляру класса. Я имею в виду, что любой конкретный фрагмент низкоуровневого кода (класса) не должен полагаться на реализацию всей системы. При этом вам нужно принять некоторые «архитектурные» решения (например, на какой платформе работать).
Возможные неожиданные прерывания, исходящие от JRE, - это отмененные задачи
java.util.concurrent
и завершение работы апплетов.Обработка прерываний потоков обычно написана неправильно. Поэтому я предлагаю архитектурное решение, чтобы избежать прерывания, где это возможно. Однако код обработки прерываний всегда должен быть написан правильно. Теперь нельзя убирать с платформы прерывания.
источник
Вы можете узнать это, создав свой собственный класс потока (расширяющий
java.lang.Thread
) иinterrupt()
метод переопределения , в котором вы записываете трассировку стека, скажем, в поле String, а затем переходите в super.interrupt ().public class MyThread extends Thread { public volatile String interruptStacktrace; // Temporary field for debugging purpose. @Override public void interrupt() { interruptStacktrace = dumpStack(); // You implement it somehow... super.interrupt(); } }
источник
Как уже упоминалось, другая библиотека может прервать ваши потоки. Даже если библиотека не имеет явного доступа к потокам из вашего кода, они все равно могут получить список запущенных потоков и прервать их таким образом с помощью следующего метода .
источник
Думаю, я понимаю, почему вас немного смущает прерывание. Пожалуйста, рассмотрите мои ответы в строке:
Во-первых, вы можете прерывать другие потоки; Я знаю, что в JCiP упоминается, что вы никогда не должны прерывать потоки, которыми вы не владеете; однако это утверждение необходимо правильно понять. Это означает, что ваш код, который может выполняться в любом произвольном потоке, не должен обрабатывать прерывания, потому что, поскольку он не является владельцем потока, он не имеет представления о его политике прерывания. Таким образом, вы можете запросить прерывание в других потоках, но позволить его владельцу взять курс на прерывание; в нем инкапсулирована политика прерывания, а не код вашей задачи; по крайней мере, будьте вежливы, чтобы установить флаг прерывания!
Есть много причин, по которым могут быть прерывания, могут быть тайм-ауты, прерывания JVM и т. Д.
Здесь нужно быть очень осторожным; если вы владеете потоком, который выбросил InterruptedException (IE), тогда вы знаете, что делать после его обнаружения, скажем, вы можете закрыть свое приложение / службу или вы можете заменить этот убитый поток новым! Однако, если вы не владеете потоком, то, поймав IE, либо перебросьте его выше по стеку вызовов, либо после чего-то (может вести журнал) сбросьте состояние прерывания, чтобы код, владеющий этим потоком, когда управление достигнет его, мог узнайте, что поток был прерван, и, следовательно, примите меры, поскольку только он знает политику прерывания.
Надеюсь, это помогло.
источник
В них
InterruptedException
говорится, что распорядок может быть прерван, но не обязательно, что это произойдет.Если вы не ожидаете прерывания, вы должны относиться к нему как к любому другому неожиданному исключению. Если он находится в критическом разделе, где непредвиденное исключение может иметь ужасные последствия, может быть лучше попытаться очистить ресурсы и корректно завершить работу (потому что получение прерывания сигнализирует, что ваше хорошо спроектированное приложение, которое не полагается на прерывания, используется в некотором смысле это не было разработано, и поэтому должно быть что-то не так). В качестве альтернативы, если рассматриваемый код не является критическим или тривиальным, вы можете проигнорировать (или зарегистрировать) прерывание и продолжить работу.
источник