Зачем бросать исключение после прерывания треда?
От: dims12 http://www.relativity.ru
Дата: 19.08.11 11:59
Оценка:
В одном примере встретил такой код:

try {
   // какие-то операции с объектом из библиотеки concurrent
} catch (InterruptedException e) {
   Thread.currentThread().interrupt();
   throw new WorkException(e);
}


Какой может быть в этом смысл? Насколько я понимаю, строка

Thread.currentThread().interrupt();


вызовет выброс InterruptedException в текущем треде и потому строка

throw new WorkException(e);


уже выполняться не будет.

Чем вообще отличается

Thread.currentThread().interrupt();


от

throw new InterruptedException();


?
Re: Зачем бросать исключение после прерывания треда?
От: avpavlov  
Дата: 19.08.11 12:23
Оценка:
D>Чем вообще отличается

так можно прервать другой поток

someThread.interrupt();

D>throw new InterruptedException();


А так не взведутся необходимые флаги, так что этот способ вообще никакого отношения к прерыванию по interrupt() не имеет
Re: Зачем бросать исключение после прерывания треда?
От: Аноним  
Дата: 19.08.11 12:31
Оценка:
Здравствуйте, dims12, Вы писали:

D>Какой может быть в этом смысл? Насколько я понимаю, строка


D>
D>Thread.currentThread().interrupt();
D>


D>вызовет выброс InterruptedException в текущем треде

D>?

Это не так, interrupt() ставит флажок что треду велено прервать выполнение, и если этот тред в данный момент находится внутри блокирующего метода типа sleep() или wait() — bp vtnjlf dsktnftn InterruptedException. При этом значение флажка сбрасывается, поэтому если нет возможности перебросить IE выше флажок ставится заново чтобы те кто выше по стеку тоже знали что интерапт был.

Вот абзац из Concurrency in Practice:
Restore the interrupt. Sometimes you cannot throw InterruptedException, for instance when
your code is part of a Runnable. In these situations, you must catch InterruptedException and
restore the interrupted status by calling interrupt on the current thread, so that code higher up the
call stack can see that an interrupt was issued, as demonstrated in Listing 5.10.
Re[2]: Зачем бросать исключение после прерывания треда?
От: dims12 http://www.relativity.ru
Дата: 19.08.11 19:46
Оценка:
Здравствуйте, avpavlov, Вы писали:

A>так можно прервать другой поток


Но в данном-то случае прерывается не другой, а этот поток?

A>А так не взведутся необходимые флаги, так что этот способ вообще никакого отношения к прерыванию по interrupt() не имеет


А, да, точно, не сообразил.
Re[2]: Зачем бросать исключение после прерывания треда?
От: dims12 http://www.relativity.ru
Дата: 19.08.11 20:03
Оценка:
Здравствуйте, Аноним, Вы писали:

А>Это не так, interrupt() ставит флажок что треду велено прервать выполнение, и если этот тред в данный момент находится внутри блокирующего метода типа sleep() или wait() —


Но тред не может, находясь внутри блокирующего метода, вызвать сам себе interrupt. Следовательно, этот вариант тут не мог иметься в виду.


A>bp vtnjlf dsktnftn InterruptedException. При этом значение флажка сбрасывается, поэтому если нет возможности перебросить IE выше флажок ставится заново чтобы те кто выше по стеку тоже знали что интерапт был.


Я так понимаю, это происходит в том случае, если тред А находится в состоянии wait, а тред Б его интерраптит. Тогда wait возвращает эксепшн. Но в данном случае тред один. Он сам себя интерраптит -- разве это не приводит к мгновенному завершению треда?

А>Restore the interrupt. Sometimes you cannot throw InterruptedException, for instance when

А>your code is part of a Runnable. In these situations, you must catch InterruptedException and
А>restore the interrupted status by calling interrupt on the current thread, so that code higher up the
А>call stack can see that an interrupt was issued, as demonstrated in Listing 5.10.

Немного понятней, но смутно. То есть, где-то ранее внутри try у нас выработался InterruptedException. Это значит, что какой-то другой тред со стороны отдал команду на прерывание данного треда. Но данный тред перехватил InterruptedException, теперь он восстанавливает флаг прерывания. Но всё равно непонятно, почему выполняется что-то после команды interrupt() на самого себя? Это первое. А второе, я припоминаю, что InterruptedException нельзя просто так перехватить, иначе тред бы мог сопротивляться команде interrupt(). Чтобы этого не происходило, InterruptedException перевыбрасывается само заново после выхода из catch. Что-то я сейчас про это не нахожу. Путаю что-то?
Re: Зачем бросать исключение после прерывания треда?
От: denis.zhdanov Россия http://denis-zhdanov.blogspot.com/
Дата: 22.08.11 08:32
Оценка:
Здравствуйте, dims12, Вы писали:

D>В одном примере встретил такой код:


D>...


здесь
http://denis-zhdanov.blogspot.com
Re[3]: Зачем бросать исключение после прерывания треда?
От: Аноним  
Дата: 22.08.11 13:39
Оценка:
Здравствуйте, dims12, Вы писали:

D>Я так понимаю, это происходит в том случае, если тред А находится в состоянии wait, а тред Б его интерраптит. Тогда wait возвращает эксепшн. Но в данном случае тред один. Он сам себя интерраптит -- разве это не приводит к мгновенному завершению треда?


Интеррапт на самом себе не приводит ни к какому завершению потому что механизм interrupt работает не так. Попробуй сам сделать
public static void main(String[] args) {
    Thread.currentThread().interrupt();
    System.out.println("hehe");
}



D>Немного понятней, но смутно. То есть, где-то ранее внутри try у нас выработался InterruptedException. Это значит, что какой-то другой тред со стороны отдал команду на прерывание данного треда. Но данный тред перехватил InterruptedException, теперь он восстанавливает флаг прерывания. Но всё равно непонятно, почему выполняется что-то после команды interrupt() на самого себя?


Потому что interrupt() всего-лишь ставит флажок что тред прерван. Выбросом исключения занимается код метода в котором находится поток в момент прерывания. Он может вообще игнорировать этот флажок, или сразу сбрасывать флаг и кидаться InterruptedException'ом как это делает sleep() и проч, что как бы говорит тебе "Я разобрался с прерыванием треда, теперь вот вам InterruptedException и разбирайтесь с ним выше по стеку". Ты, как ловец InterruptedException волен разобраться с ситуацией подобающим образом и сообщить наверх что случилась такая вот фигня, тред был прерван. Судя по всему, в коде из примера (там где ставится флажок и кидается некий WorkException) ожидается что в catch блоке этого WorkException дополнительно будет проверен флажок прервывания и от этого что-то будет зависеть. Или не будет проверяться, а вместо этого будет проверен ещё выше по стеку.

D> Это первое. А второе, я припоминаю, что InterruptedException нельзя просто так перехватить, иначе тред бы мог сопротивляться команде interrupt(). Чтобы этого не происходило, InterruptedException перевыбрасывается само заново после выхода из catch. Что-то я сейчас про это не нахожу. Путаю что-то?


Во-первых, путаешь. Во-вторых, ленишься проверить это на практике и вместо того чтобы написать 10 строк кода спрашиваешь об этом на форуме.
Thread thread = new Thread(new Runnable() {
    @Override
    public void run() {
        try {
            Thread.sleep(Integer.MAX_VALUE);
        } catch (InterruptedException e) {
            System.out.println("Has been interrupted");
        }
        System.out.println("Out of try block");
    }
});
thread.start();
thread.interrupt();


Ну что, перебросилось "само заново после выхода из catch"?
Читай книжку с поездами http://www.amazon.com/Java-Concurrency-Practice-Brian-Goetz/dp/0321349601
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.