#java #concurrency #blockingqueue #interrupted-exception
#java #параллелизм #blockingqueue #прерванное исключение
Вопрос:
У меня есть этот фрагмент кода. LinkedBlockingQueue
Должен выдавать только Exception
, если прерывается во время ожидания добавления в очередь. Но эта очередь не ограничена, поэтому ее следует добавить как можно скорее. Почему мой метод завершения работы выдает InterruptedException
?
private final LinkedBlockingQueue<Message> messages= new LinkedBlockingQueue<Message>();
public void run(){
LinkedList<Message> messages = new LinkedList<Message>();
while (true){
try{
messages.clear();
messages.add(this.messages.take());
this.messages.drainTo(messages);
for (Message message:messages){
if(message.isPoison())return;
doSomething(message);
}
}catch(Exception e){
getLogger().addException(e);
}
}
}
protected void add(Message m){
try {
messages.put(m);
}catch (InterruptedException e) {
getLogger().addException(e);
addRollback(e);
}
}
public void shutdown(){
try{
messages.put(MessageFactory.getPoison());
}catch(InterruptedException e){
//here an exception is thrown. Why?
}
}
Комментарии:
1. Вы всегда получаете исключение прерывания при каждом вызове shutdown. Откуда вы вызываете завершение работы? Также немного сбивает с толку то, что у вас есть две переменные с именами messages.
2. При запуске может случиться так, что завершение работы должно быть выполнено из-за неправильной версии. Приложение запускает множество потоков и в то же время должно снова их закрыть. Таким образом, может быть, что завершение работы вызывается во время запуска потока. Но это не должно быть проблемой?
3. Всегда ли вызов shutdown вызывает исключение InterruptedException? Можете ли вы распечатать трассировку стека?
Ответ №1:
Если поток находится в состоянии прерывания, то есть Thread.interrupted() == true, тогда вызов выдаст InterruptionException
. Это не обязательно означает, что поток был прерван во время put
ввода, он мог уже находиться в состоянии перед входом.
Комментарии:
1. Происходит ли это при запуске потока? Так что, вместо этого лучше использовать add?
2. Поток при запуске никогда не должен прерываться. Вы можете использовать add , но если очередь заполнена, MessageFactory.getPoison() никогда не будет добавлен в очередь (при условии, что реализация изменится на ArrayBlockingQueue или вы добавите ограничение по размеру). Вы должны попытаться выяснить, где или почему прерывается поток. Например, если вы используете исполнителя, Future.cancel(true) прервет поток.