Тимур Машнин

Многопоточное программирование в 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 ().

      Синхронизация потоков

      Теперь, когда мы рассмотрели потоки, давайте разберем ключевую концепцию в многопоточном программировании, которая идет рука об руку с потоками, и это блокировки.

      Потоки взаимодействуют между собой, главным образом, путем совместного доступа к полям объектов.

      Это взаимодействие делает возможными два вида ошибок: интерференция потоков и ошибки согласованности памяти.

      Предположим, что у нас есть очень простой метод объекта, который принимает число и увеличивает его на единицу.