Java: Как мне перехватить InterruptedException в потоке, когда он прерывается другим потоком?
Я разрабатываю многопоточное приложение для подключения к внешним серверам - каждый в отдельных потоках - и будет заблокировано до тех пор, пока не будет введен ввод. Каждый из них расширяет класс Thread. Для пояснения давайте назовем эти "потоки соединения".
Все эти потоки соединений хранятся в параллельной хэш-карте.
Затем я разрешаю вызов метода веб-служб RESTful для отмены любого из потоков. (Я использую Grizzly/Jersey, поэтому каждый вызов является отдельным потоком.)
Я извлекаю конкретный поток соединения (из hashmap) и вызываю для него метод interrupt().
Итак, вот вопрос, в потоке соединения, как я могу поймать InterruptedException? (Я хотел бы что-то сделать, когда поток соединения остановлен внешней командой RESTful.)
5 ответов
Итак, вот вопрос, в потоке соединения, как я могу поймать InterruptedException?
Ты не можешь. Поскольку, если ваш поток заблокирован на операции чтения ввода-вывода, это не может быть interrupted
, Это потому что interrupt
просто устанавливает флаг, чтобы указать, что поток был прерван. Но если ваш поток заблокирован для ввода / вывода, он не увидит флаг.
Правильный способ для этого - закрыть базовый сокет (для которого поток заблокирован), затем перехватить исключение и распространить его.
Так как ваши темы подключения extend Thread
сделайте следующее:
@Override
public void interrupt(){
try{
socket.close();
}
finally{
super.interrupt();
}
}
Таким образом, можно прервать поток, заблокированный на вводе / выводе.
Тогда в вашем run
метод сделать:
@Override
public void run(){
while(!Thread.currentThread().isInterrupted()){
//Do your work
}
}
Так что в вашем случае не пытайтесь catch
InterruptedException
, Вы не можете прервать поток, заблокированный на ввод-вывод. Просто проверьте, был ли прерван ваш поток, и упростите его, закрыв поток.
Проблема с блокировкой.
Hoverer, попробуйте этот код, может быть, он поможет вам:
try{
yourObject.read();
}catch(InterruptedException ie){
// interrupted by other thread
}
catch(Exception ex){
// io or some other exception happent
}
Ваш метод чтения должен проверить, есть ли доступные байты в сокете, например, если есть, чем читать, в противном случае перейдите в режим Speel. Когда спит, чем доступно, пробуждение (InterruptedException) при чтении чистых сокетов (что бы вы ни читали) будет заблокировано. Некоторый API имеет значение для максимального ожидания, например, 5 с 60 с, если ничего не прочитано, чем будет следующий код выполнения.
class MyReadingObject
{
public read() throws InterruptedException{
while(shouldIread){
if(socket.available() > 0){
byte[] buff = new byte[socket.avaialble()]
socket.read(buff);
return;
}
else{
Thread.currentThread.sleep(whateverMilliseconds);
}
}
}
}
как то так, но с обработкой ошибок и некоторыми шаблонами проектирования
Когда вы звоните Thread.interrupt()
в каком-то потоке происходит то, что для этого потока установлен флаг 'прерывания'. Некоторые методы проверяют этот флаг Thread.interrupted()
или же Thread.isInterrupted()
) и бросить InterruptedException
, но обычно только методы, которые могут блокировать, делают это. Так что нет никаких гарантий, что InterruptedException
будет когда-либо брошен в прерванной нити. Если вы не вызываете метод, который бросает InterruptedException
нет смысла перехватывать это исключение, поскольку оно вообще не будет выброшено. Однако вы всегда можете проверить, была ли прервана ваша нить, вызвав Thread.isInterrupted()
,
Призвание interrupt()
на потоке не останавливает его, он просто включает флаг прерывания. Код отвечает за изменение состояния прерывания рассматриваемого потока и принятие соответствующих мер. Если вы выполняете операцию блокировки в этом потоке, вы в значительной степени SOL, потому что ваш поток "блокирует" чтение. Посмотрите на ответ, который я разместил здесь. Так что, по сути, если вы не просматриваете что- то или периодически проверяете некоторые флаги внутри этого потока, у вас нет способа вырваться без закрытия сокетов или чего-то в этом роде.
Одним из решений здесь является "явное" раскрытие базового объекта соединения и вызов close()
вынуждая его генерировать какое-то исключение, которое затем может быть обработано в поточном коде. Что-то вроде:
class MyAction extends Thread implements Disposable {
public void doStuff() {
try {
byte[] data = this.connection.readFully();
} catch (InterruptedException e) {
// possibly interrupted by forceful connection close
}
@Override
public void dispose() {
this.connection.close();
}
}
// Elsewhere in code
MyAction action = conMap.get("something");
action.dispose();
Используйте try-catch, например, так:
try {
//code
} catch ( InterruptedException e) {
//interrupted
}
Я думаю, что это должно сработать, вы также можете оставить логическую переменную для выхода, чтобы они проверяли эту переменную, если она истинна, останавливали