Выполняется ли блок finally, если поток, выполняющий функцию, прерван?

Если у меня есть функция с секцией try/finally, и поток, выполняющий ее, прерывается, пока в блоке try будет выполнен блок finally до того, как произойдет перерыв?

12
добавлено автор Santosh, источник
Ну, я отметил вопрос как «java», и я упомянул try/finally, поэтому я решил, что я могу понять, что я говорю о прерывании потоков в Java ...
добавлено автор user940016, источник
Вы должны прояснить, что вы подразумеваете под «прерванным» - это слово перегружено: (Это означает разные вещи разработчикам прошивки/драйвера, разработчикам ОС и разработчикам java.
добавлено автор Martin James, источник

6 ответы

According to the Java Tutorials, "if the thread executing the try or catch code is interrupted or killed, the finally block may not execute even though the application as a whole continues."

Вот полный отрывок:

Блок finally always выполняется, когда блок try завершается. Эта   гарантирует, что блок finally выполняется, даже если неожиданное   исключение. Но finally полезен не только для исключения   обработка - это позволяет программисту избежать кода очистки   случайно минуя return , continue или break . Помещение очистки   код в блоке finally всегда является хорошей практикой, даже если нет   исключения ожидаются.

     

Примечание. Если JVM завершает работу, пока выполняется код try или catch , тогда   блок finally может не выполняться. Аналогично, если выполнение потока   код try или catch прерван или убит, блок finally может   не выполняются, даже если приложение в целом продолжается.

class Thread1 implements Runnable {

    @Override
    public void run() {
        try {
            Thread.sleep(10000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            System.out.println("finally executed");
        }
    }
}

...

t1.start();
t1.interrupt();

It prints - finally executed

7
добавлено
@Risadinha: восстановление флага прерывания не может заставить блок finally быть выполненным здесь. Это повлияет только на то, будет ли какой-либо другой код, выполняемый этим потоком, определить, был ли поток прерван. Не имея этого, это не влияет на действительность теста Субграйоти.
добавлено автор Nathan Hughes, источник
Фактически, он работает только потому, что прерывается. Вы неправильно обрабатываете InterruptedException, поскольку вы просто глотаете его. Вы должны распространять его либо путем повторного металирования, либо путем вызова Thread.currentThread.interrupt (). Для получения дополнительной информации см. ibm.com/developerworks/java/library /j-jtp05236/index.html . Тогда возникает вопрос - будет ли наконец закончен?
добавлено автор Risadinha, источник
Один предположил, что это относится к собственному потоку, к которому связанный поток java прерывается на системном уровне, а не прерывание потока Java.
добавлено автор Affe, источник
@Risadinha, вот ответ на поднятый вами вопрос: stackoverflow.com/a/33436444/3050466 . Большой вопрос BTW!
добавлено автор Keenle, источник
@sjlee - Спасибо за комментарий, я тестировал код. Его работа, как я сказал.
добавлено автор Subhrajyoti Majumder, источник
Хм ... Я понимаю, что, наконец, не получается выполнить, если поток убит. Однако прерывание потока должно NOT остановить выполнение предложения finally. Я не знаю, почему в этом отрывке говорится об этом. Вот описание JLS в его полной славе: docs.oracle.com/javase/specs/jls/se7/html/…
добавлено автор sjlee, источник
Хорошо, вы имеете в виду, что, наконец, DOES выполняется, даже если поток прерывается, правильно? Если это так, ваш ответ должен быть уточнен. Звучит так, как будто, наконец, может не выполняться, если поток прерывается.
добавлено автор sjlee, источник

Многие из учебных пособий Oracle по Java полезны (у меня есть ответы, ссылающиеся на страницу охраняемых блоков и введение SAX), но они не обязательно являются авторитетными, а некоторые из них имеют ошибки или являются неполными. Котировка, на которую ссылается в вопросе, препятствует прерыванию с выходом JVM, что вызывает недоумение.

Во-первых, прерывание потока в Java не имеет ничего общего с прерываниями на уровне ОС. Совместное использование имени создает возможности для путаницы, но соединение отсутствует .

Далее, выход JVM, очевидно, убивает поток без возможности выполнить любую очистку. Если процесс замирает до того, как поток дошел до блока finally, слишком плохо. Но нет никакого сравнения с прерыванием. Ничто в прерывании не позволяет окончательно блокировать завершение.

Принцип прерывания заключается в том, что действие на прерывание требует взаимодействия нити, которая прерывается. Прерывание потока отвечает по своему усмотрению, прерывание не заставляет поток ничего делать. Все вызовы Thread # interrupt() устанавливают флаг в потоке. Блокирующие методы, такие как wait или sleep, проверяют флаг, чтобы увидеть, должны ли они просыпаться раньше. (InterruptedException - проверенное исключение, поэтому вы можете указать, кто его выдает, и ваш Runnable может его планировать.) Также любой код может использовать Thread # isInterrupted (), чтобы проверить, установлен ли его поток установленным флагом.

Когда Thread # sleep() распознает, что прерванный флаг установлен, он очищает флаг перед тем, как бросать InterruptedException. Когда ваш поток попадает в InterruptedException, хорошие манеры восстанавливают флаг с помощью Thread.currentThread (). Interrupt (), на всякий случай, если в этом потоке есть какой-либо другой код, который должен знать о прерывании. Это вступает в игру, когда у вас более сложные ситуации с вложенными синхронизаторами, где, например, какой-то глубоко вложенный компонент может прерывать свой сон, позволяя ему оставаться очищенным, может помешать более высоким уровням узнать о прерывании. В простом примере игрушек, подобном тому, который содержится в других ответах здесь, не имеет значения, восстановлен ли флаг или нет, ничто не проверяет его снова, и поток завершается.

4
добавлено
@Joe: от чтения большого количества книг, таких как Java Concurrency на практике, и от попыток сделать это для себя. Было ли что-то особенное, где вы хотели знать, откуда оно взялось?
добавлено автор Nathan Hughes, источник
Где вы получаете эту информацию?
добавлено автор Joe, источник

Прерывание потока в Java просто устанавливает флаг. Это не вызывает ничего особенного в том, что происходит с выполнением кода или влияет на поток управления.

Если ваш поток задействован или пытается ввести операцию, которая выдает InterruptedException, тогда исключение вызывается из того места, где этот метод вызывается, и если он находится внутри блока try, то, наконец, будет выполняться до того, как исключение останется как обычный ,

4
добавлено
@Joe, как один «контрольный» поток заставляет другой поток «оканчиваться» в рамках вопроса, будучи тем, что вы можете сделать в java-языке? Даже устаревший и сильно злокачественный thread.stop приведет к тому, что остановленный поток войдет в блок finally.
добавлено автор Affe, источник

В комментариях в ответ , @Risadinha задал очень правильный вопрос о том, находится ли код в блоке finally выполняется, если мы восстанавливаем флаг прерывания внутри блока catch , вызывая Thread.currentThread (). interrupt() .

Вот небольшой фрагмент кода для тестирования:

final SomeContext context = new SomeContext();
Thread thread = new Thread() {
    @Override
    public void run() {
        try {
            Thread.sleep(10000);
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
        } finally {
           //this code gets executed even though
           //we interrupt thread in catch block.
            context.value = 9;  
        }
    }
};

thread.start();
thread.interrupt();

thread.join();//need to wait for thread code to complete

assertEquals(context.value, 9);//values are the same!

Код класса SomeContext:

class SomeContext {
    public volatile int value = 10;
}
3
добавлено
Спасибо за этот тест. Хотя в блоке finally я еще не поставил критически важный код, увидев, что в учебниках Java указано, что нет гарантии, что он будет выполняться, если поток будет прерван или убит. Возможно, это зависит от JVM/Vendor/Version и/или ресурсов и т. Д.
добавлено автор Risadinha, источник

Эффект прерывания заключается в том, чтобы вызывать InterruptedException в следующий раз при операции блокировки (на практике при следующем вызове метода, который указывает, что он может вызывать InterruptedException ), в какой момент - как обычно - выполняется нормальный поток try/catch , который действительно выполняет блок finally после try и любой применимый catch es.

1
добавлено

Он будет выполняться так же, как и с любым другим исключением из блока try, а не до прерывания.

0
добавлено
pro.jvm
pro.jvm
3 503 участник(ов)

Сообщество разработчиков Java Scala Kotlin Groovy Clojure Чат для нач-их: @javastart Наш сайт: projvm.com projvm.ru Наш канал: @proJVM Вакансии: @jvmjobs Конфы: @jvmconf

Java & Co
Java & Co
2 370 участник(ов)

Можно обсуждать с матом и без всё, что касается жабы, вплоть до холиваров. НЕ ИМЕЕТ ОТНОШЕНИЯ К САЙТУ JAVARUSH.RU ПРАВИЛА - https://t.me/javarush/75723 Вакансии сюда - https://telegram.me/joinchat/B7IzvUCnfo6d8t3yIxKguQ По вопросам - @thedude

learn.java
learn.java
1 888 участник(ов)

Чат для начинающих и не только Статистика: https://combot.org/chat/-1001083535868 Основной чат - @jvmchat

Java Underground
Java Underground
169 участник(ов)

https://vk.com/javatutorial

Javanese Questions
Javanese Questions
109 участник(ов)

Чат предназначен для обмена знаниями строго в формате в вопрос-ответ. Тема — Java, Kotlin и Android. Вопрос должен быть предварительно прогуглен, понятно и грамотно сформулирован, помечен хэштегами. Ответ — тем более. Куски кода размером в несколько строк можно писать прямо здесь, для больших кусков кода стоит использовать http://gist.github.com/, http://pastebin.com/, https://codeshare.io/ или любой аналогичный сервис. В некоторых случаях можно прикреплять скриншоты. Стикеры и гифки запрещены. Дополнять и уточнять вопросы и ответы — редактированием исходного сообщения. Обсуждения должны приводить к редактированию вопроса/ответа и удаляться. По хештегам можно искать существующие вопросы и овтеты: #вопрос #ответ #git #generics #java #server #awt #javafx #swing #kotlin #anko #tornadofx #ktor #android #recyclerView #performance #arch #network #permissions #storage #async