Многопоточное программирование в Java. Тимур Машнин
Читать онлайн книгу.когда вам нужно выполнить некоторые длительные задачи в отдельных потоках.
И возможно, вам нужно будет завершить работу какой-либо задачи еще до того, как задача будет полностью выполнена, с помощью остановки соответствующего потока.
Например, при закрытии приложения, которое может использовать несколько потоков, и они могут быть не завершены в момент закрытия приложения.
Как запросить задачу, выполняемую в отдельном потоке, закончиться раньше?
Как заставить задачу реагировать на такой запрос?
В этом примере создается задача, которая печатает числа от 0 до 9 в консоли.
После печати числа, задача должна подождать 1 секунду перед печатью следующего числа.
Задача выполняется в отдельном потоке, отличном от основного потока приложения.
После запуска задачи основной поток должен подождать 3 секунды и затем завершить работу.
При завершении работы приложение должно запросить завершение выполняемой задачи.
Перед тем, как полностью закрыть приложение, приложение должно максимально ждать 1 сек для завершения задачи.
Задача должна ответить на запрос завершения, немедленно останавливаясь.
Общее выполнение задачи занимает не менее 9 секунд.
Поэтому задача не сможет распечатать все десять чисел от 0 до 9.
Для запроса на прерывание потока, основной поток вызывает метод прерывания interrupt.
В Java один поток не может просто остановить другой поток.
Поток может только запросить остановку другого потока.
И запрос выполняется в виде вызова метода interrupt.
Вызов метода interrupt в экземпляре Thread устанавливает флаг прерывания как true.
Если этот поток заблокирован вызовом методов wait, join или sleep, то его статус прерывания будет очищен, и он выбросит исключение InterruptedException.
Таким образом, как только taskThread прерывается основным потоком, Thread.sleep (1000) отвечает на прерывание, выбрасывая исключение.
Исключение InterruptedException обрабатывается, прерывая цикл и тем самым заканчивая задачу раньше.
Таким образом, чтобы задача немедленно реагировала на запрос прерывания, можно использовать обработку исключения InterruptedException.
После очистки статуса прерывания, подтвердить этот статус можно самопрерыванием с помощью вызова Thread.currentThread().interrupt ().
И без использования обработки InterruptedException, прервать цикл задачи можно, проверяя статус прерывания с помощью вызова Thread.isInterrupted ().
Синхронизация потоков
Теперь, когда мы рассмотрели потоки, давайте разберем ключевую концепцию в многопоточном программировании, которая идет рука об руку с потоками, и это блокировки.
Потоки взаимодействуют между собой, главным образом, путем совместного доступа к полям объектов.
Это взаимодействие делает возможными два вида ошибок: интерференция потоков и ошибки согласованности памяти.
Предположим, что у нас есть очень простой метод объекта, который принимает число и увеличивает его на единицу.