Что такое мьютекс java

Использование объекта мьютекса в Java

Исследуйте концепцию объекта мьютекса в Java.

1. Обзор

2. Мьютекс

В многопоточном приложении двум или более потокам может потребоваться доступ к общему ресурсу одновременно, что приводит к неожиданному поведению. Примерами таких общих ресурсов являются структуры данных, устройства ввода-вывода, файлы и сетевые подключения.

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

3. Почему мьютекс?

Во-первых, давайте возьмем пример Генератора последовательностей класса, который генерирует следующую последовательность, увеличивая currentValue на единицу каждый раз:

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

Как только мы выполним этот тестовый случай, мы увидим, что он в большинстве случаев терпит неудачу по причине, аналогичной:

Предполагается, что уникальные последовательности имеют размер, равный количеству раз, когда мы выполняли метод getNextSequence в нашем тестовом примере. Однако это не так из – за состояния гонки. Очевидно, что мы не хотим такого поведения.

Существуют различные способы реализации мьютекса в Java. Итак, далее мы рассмотрим различные способы реализации мьютекса для нашего генератора последовательностей класса.

4. Использование синхронизированного ключевого слова

Каждый объект в Java имеет внутреннюю блокировку, связанную с ним. Метод /synchronized и | блок synchronized используют эту встроенную блокировку для ограничения доступа к критической секции только одним потоком за раз.

Давайте изменим getNextSequence на мьютекс, просто добавив ключевое слово synchronized :

Итак, давайте теперь посмотрим, как мы можем использовать блок synchronized для синхронизации на пользовательском объекте мьютекса :

5. Использование ReentrantLock

Класс ReentrantLock был представлен в Java 1.5. Он обеспечивает большую гибкость и контроль, чем подход synchronized keyword.

Давайте посмотрим, как мы можем использовать ReentrantLock для достижения взаимного исключения:

6. Использование Семафора

Теперь давайте создадим еще одну потокобезопасную версию Генератора последовательностей с использованием Семафора :

7. Использование класса монитора Гуавы

До сих пор мы видели варианты реализации мьютекса с использованием функций, предоставляемых Java.

Во-первых, мы добавим зависимость Maven для Guava :

8. Заключение

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

Источник

Мютекс и монитор

В своих предыдущих лекциях я иногда использовала слова «мютекс» и «монитор», теперь настало время рассказать, что же это значит.

Мютекс – это специальный объект для синхронизации нитей/процессов. Он может принимать два состояния – занят и свободен. Если упростить, то мютекс – это boolean-переменная, которая принимает два значения: занят(true) и свободен(false).

Когда нить хочет монопольно владеть некоторым объектом, она помечает его мютекс занятым, а когда закончила работу с ним – помечает его мютекс свободным.

— Т.е. мютекс – это как табличка на двери – занят/свободен?

— Да. И такой мютекс прикреплен к каждому объекту в Java. Прямой доступ к мютексу есть только у Java-машины. От программиста он скрыт.

— А как же тогда его использовать?

— А работать с мютексом в Java можно посредством монитора.

Монитор – это специальный механизм (кусок кода) – надстройка над мютексом, который обеспечивает правильную работу с ним. Ведь мало пометить, что объект – занят, надо еще обеспечить, чтобы другие нити не пробовали воспользоваться занятым объектом.

В Java монитор реализован с помощью ключевого слова synchronized.

Когда ты пишешь блок synchronized, то компилятор Java заменяет его тремя кусками кода:

1) В начале блока synchronized добавляется код, который отмечает мютекс как занятый.

2) В конце блока synchronized добавляется код, который отмечает мютекс как свободный.

3) Перед блоком synchronized добавляется код, который смотрит, если мютекс занят – то нить должна ждать его освобождения.

Вот как это примерно работает:

КодКак это работаетОписание
Нить спит, пока мютекс занят
(выйдем из цикла, когда мютекс освободится) Помечаем мютекс занятым

Помечаем мютекс свободным

На самом деле логика там другая и сложнее, но это уже детали.

— А можно подробности?

— Пока не научишься правильно этим пользоваться – в детали лезть нет смысла.

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

— Не очень. Просто все быстро забывается…

— Чем меньше практики, тем меньше пользы и от теории.

Вот уровню к 40 научишься всем этим пользоваться, и я тебе объясню, как все устроено на самом деле. А пока — учись просто правильно всем пользоваться. Ясно?

Источник

Java для начинающих: часть 3 из 4

Что такое мьютекс java. Смотреть фото Что такое мьютекс java. Смотреть картинку Что такое мьютекс java. Картинка про Что такое мьютекс java. Фото Что такое мьютекс java

Nov 7, 2018 · 8 min read

Что такое мьютекс java. Смотреть фото Что такое мьютекс java. Смотреть картинку Что такое мьютекс java. Картинка про Что такое мьютекс java. Фото Что такое мьютекс java

Данные статьи помогут легко и быстро разобраться в концепциях и программировании на Java. Даже при нулевых знаниях в Java трудностей в освоении этих материалов не возникнет. А опытные Java-разработчики смогут освежить свои знания.

Потоки

Способы работы с потоками:

1. Расширение класса Thread.

2. Реализация интерфейса Runnable.

Что такое мьютекс java. Смотреть фото Что такое мьютекс java. Смотреть картинку Что такое мьютекс java. Картинка про Что такое мьютекс java. Фото Что такое мьютекс java

Object.wait() → Блокировка потока до вызова уведомления.

Object.notify() → Пробуждает поток, ожидающий на мониторе указанного объекта, и переводит его в «работоспособное» состояние (Runnable mode).

Object.notifyAll() → Пробуждает все потоки, ожидающие на мониторе данного объекта.

Thread.yield() → Переводит текущий поток в «работоспособное» состояние и переходит к следующему потоку.

Th r ead.sleep() → На несколько миллисекунд переводит поток в спящее/приостановленное состояние. Время в методе sleep передается как параметр.

Мьютекс и семафор

Обработка ошибок

Что такое мьютекс java. Смотреть фото Что такое мьютекс java. Смотреть картинку Что такое мьютекс java. Картинка про Что такое мьютекс java. Фото Что такое мьютекс java

Класс Observable и интерфейс Observer

1. Создается класс наблюдаемых — Observable.

2. Добавляется несколько классов наблюдателей — Observer.

3. Регистрируются классы Observer в объекте Observable (addObserver).

4. Вызывается notifyObserver для уведомления всех наблюдателей о произошедшем событии.

Существуют 3 типа запросов в JDBC:

2. PreparedStatement: однократная компиляция запроса. Производительность здесь в разы выше.

3. CallableStatement: исполняет процедуры и функции.

Чтение и запись файла

ByteStream — для чтения и записи бинарных данных.

CharacterStreams работает с символами, а не байтами.

FileInputStream содержит входной байт из файла и реализует входной стрим.

FileOutputStream: записывает данные в файл и реализует выходной стрим.

Чтение из файла: Общий способ чтения символов из файла — через класс FileReader. Класс BufferedReader можно обернуть вокруг любого Reader (например, FileReader) для буферизации входных данных и увеличения эффективности.

Пример названия файла: “C:/Users/chellapilla_m/Desktop/task.txt”

Запись в файл: Ниже приведен пример записи в файл через FileOutputStream.

FileOutputStream нужен для записи стримов сырых байтов (raw byte). К примеру, информация об изображении. Для записи стримов из символов лучше использовать FileWriter.

Шаблоны проектирования

Это самый популярный шаблон проектирования в Java. Здесь мы создаем объект без демонстрации логики создания клиенту и обращаемся к недавно созданным объектам через общий интерфейс. Пример:

Обеспечивает совместную работу двух несвязанных интерфейсов. Пример:

Это ответвление шаблона «Фабрика». Класс Builder создает сложный объект в несколько этапов.

Важные моменты

Вопрос: Зачем нужна функция main()?

Выполнение программы начинается с метода main().

Вопрос: Почему метод main() публичный?

Так метод доступен для JVM — она начинает выполнение программы вне класса.

Вопрос: Почему main() статичный?

Для его исполнения не нужен объект.

Вопрос: Почему String args[]?

Параметры — это аргументы командной строки. Просто так вышло, что разработчик Java счел их обязательными. Никакой особой нагрузки они не несут.

Вопрос: Для чего нужен out в System.out.println()?

«out» — это объект класса PrintStream и статический член класса System, который вызывает функцию println().

Вопрос: Как в Java реализован Random?

Класс java.util.Random реализует линейный конгруэнтный метод.

где m, c и a — константы, а i — выбранное начальное значение.

Вопрос: Что такое regex в Java?

Регулярные выражения (regex) определяют поисковый образ строк.

Вопрос: Чем отличаются вложенные и внутренние классы?

Внутренними называются не статичные вложенные классы.

Вопрос: Что такое вложенный интерфейс?

Это любой интерфейс, объявленный в классе или интерфейсе. Всегда статичный по умолчанию.

Источник

Внутри процесса: многопоточность и пинг-понг mutex’ом

Что такое мьютекс java. Смотреть фото Что такое мьютекс java. Смотреть картинку Что такое мьютекс java. Картинка про Что такое мьютекс java. Фото Что такое мьютекс java

Что такое мьютекс java. Смотреть фото Что такое мьютекс java. Смотреть картинку Что такое мьютекс java. Картинка про Что такое мьютекс java. Фото Что такое мьютекс java

Что такое мьютекс java. Смотреть фото Что такое мьютекс java. Смотреть картинку Что такое мьютекс java. Картинка про Что такое мьютекс java. Фото Что такое мьютекс java

Какая тема вызывает больше всего вопросов и затруднений у начинающих? Когда я спросила об этом преподавателя и Java-программиста Александра Пряхина, он сразу ответил: «Многопоточность». Спасибо ему за идею и помощь в подготовке этой статьи!

Мы заглянем во внутренний мир приложения и его процессов, разберёмся, в чём суть многопоточности, когда она полезна и как её реализовать — на примере Java. Если учите другой язык ООП, не огорчайтесь: базовые принципы одни и те же.

О потоках и их истоках

Чтобы понять многопоточность, сначала вникнем, что такое процесс. Процесс – это часть виртуальной памяти и ресурсов, которую ОС выделяет для выполнения программы. Если открыть несколько экземпляров одного приложения, под каждый система выделит по процессу. В современных браузерах за каждую вкладку может отвечать отдельный процесс.

Вы наверняка сталкивались с «Диспетчером задач» Windows (в Linux это — «Системный монитор») и знаете, что лишние запущенные процессы грузят систему, а самые «тяжёлые» из них часто зависают, так что их приходится завершать принудительно.

Но пользователи любят многозадачность: хлебом не корми — дай открыть с десяток окон и попрыгать туда-сюда. Налицо дилемма: нужно обеспечить одновременную работу приложений и при этом снизить нагрузку на систему, чтобы она не тормозила. Допустим, «железу» не угнаться за потребностями владельцев — нужно решать вопрос на программном уровне.

Мы хотим, чтобы в единицу времени процессор успевал выполнить больше команд и обработать больше данных. То есть нам надо уместить в каждом кванте времени больше выполненного кода. Представьте единицу выполнения кода в виде объекта — это и есть поток.

К сложному делу легче подступиться, если разбить его на несколько простых. Так и при работе с памятью: «тяжёлый» процесс делят на потоки, которые занимают меньше ресурсов и скорее доносят код до вычислителя (как именно — см. ниже).

У каждого приложения есть как минимум один процесс, а у каждого процесса — минимум один поток, который называют главным и из которого при необходимости запускают новые.

Разница между потоками и процессами

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

Процессы работают каждый со своими данными — обмениваться чем-то они могут только через механизм межпроцессного взаимодействия. Потоки обращаются к данным и ресурсам друг друга напрямую: что изменил один — сразу доступно всем. Поток может контролировать «собратьев» по процессу, в то время как процесс контролирует исключительно своих «дочек». Поэтому переключаться между потоками быстрее и коммуникация между ними организована проще.

Какой отсюда вывод? Если вам нужно как можно быстрее обработать большой объём данных, разбейте его на куски, которые можно обрабатывать отдельными потоками, а затем соберите результат воедино. Это лучше, чем плодить жадные до ресурсов процессы.

Но почему такое популярное приложение как Firefox идёт по пути создания нескольких процессов? Потому что именно для браузера изолированная работа вкладок — это надёжно и гибко. Если с одним процессом что-то не так, не обязательно завершать программу целиком — есть возможность сохранить хотя бы часть данных.

Что такое многопоточность

Вот мы и подошли к главному. Многопоточность — это когда процесс приложения разбит на потоки, которые параллельно — в одну единицу времени — обрабатываются процессором.

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

Многопоточные приложения можно запускать и на одноядерных процессорах, но тогда потоки выполняются по очереди: первый поработал, его состояние сохранили — дали поработать второму, сохранили — вернулись к первому или запустили третий, и т.д.

Что такое мьютекс java. Смотреть фото Что такое мьютекс java. Смотреть картинку Что такое мьютекс java. Картинка про Что такое мьютекс java. Фото Что такое мьютекс java

Занятые люди жалуются, что у них всего две руки. Процессы и программы могут иметь столько рук, сколько нужно для скорейшего выполнения задачи.

Жди сигнала: синхронизация в многопоточных приложениях

Представьте, что несколько потоков пытаются одновременно изменить одну и ту же область данных. Чьи изменения будут в итоге приняты, а чьи — отменены? Чтобы работа с общими ресурсами не приводила к путанице, потокам нужно координировать свои действия. Для этого они обмениваются информацией с помощью сигналов. Каждый поток сообщает другим, что он сейчас делает и каких изменений ждать. Так данные всех потоков о текущем состоянии ресурсов синхронизируются.

В категориях объектно-ориентированного программирования сигналы — это объекты синхронизации. У каждого из них — своя роль во взаимодействии.

Основные средства синхронизации

Взаимоисключение (mutual exclusion, сокращённо — mutex) — «флажок», переходящий к потоку, который в данный момент имеет право работать с общими ресурсами. Исключает доступ остальных потоков к занятому участку памяти. Мьютексов в приложении может быть несколько, и они могут разделяться между процессами. Есть подвох: mutex заставляет приложение каждый раз обращаться к ядру операционной системы, что накладно.

Семафор — позволяет вам ограничить число потоков, имеющих доступ к ресурсу в конкретный момент. Так вы снизите нагрузку на процессор при выполнении кода, где есть узкие места. Проблема в том, что оптимальное число потоков зависит от машины пользователя.

Событие — вы определяете условие, при наступлении которого управление передаётся нужному потоку. Данными о событиях потоки обмениваются, чтобы развивать и логически продолжать действия друг друга. Один получил данные, другой проверил их корректность, третий — сохранил на жёсткий диск. События различаются по способу отмены сигнала о них. Если нужно уведомить о событии несколько потоков, для остановки сигнала придётся вручную ставить функцию отмены. Если же целевой поток только один, можно создать событие с автоматическим сбросом. Оно само остановит сигнал, после того как он дойдёт до потока. Для гибкого управления потоками события можно выстраивать в очередь.

Критическая секция — более сложный механизм, который объединяет в себе счётчик цикла и семафор. Счётчик позволяет отложить запуск семафора на нужное время. Преимущество в том, что ядро задействуется лишь в случае, если секция занята и нужно включать семафор. В остальное время поток выполняется в пользовательском режиме. Увы, секцию можно использовать только внутри одного процесса.

Как реализовать многопоточность в Java

За работу с потоками в Java отвечает класс Thread. Создать новый поток для выполнения задачи — значит создать экземпляр класса Thread и связать его с нужным кодом. Сделать это можно двумя путями:

образовать от Thread подкласс;

имплементировать в своём классе интерфейс Runnable, после чего передавать экземпляры класса в конструктор Thread.

Пока мы не будем затрагивать тему тупиковых ситуаций (deadlock’ов), когда потоки блокируют работу друг друга и зависают — оставим это для следующей статьи. А сейчас перейдём к практике.

Пример многопоточности в Java: пинг-понг мьютексами

Если вы думаете, что сейчас будет что-то страшное — выдохните. Работу с объектами синхронизации мы рассмотрим почти в игровой форме: два потока будут перебрасываться mutex’ом. Но по сути вы увидите реальное приложение, где в один момент времени только один поток может обрабатывать общедоступные данные.

Сначала создадим класс, наследующий свойства уже известного нам Thread, и напишем метод «удара по мячу» (kickBall):

Теперь позаботимся о мячике. Будет он у нас не простой, а памятливый: чтоб мог рассказать, кто по нему ударил, с какой стороны и сколько раз. Для этого используем mutex: он будет собирать информацию о работе каждого из потоков — это позволит изолированным потокам общаться друг с другом. После 15-го удара выведем мяч из игры, чтоб его сильно не травмировать.

А теперь на сцену выходят два потока-игрока. Назовём их, не мудрствуя лукаво, Пинг и Понг:

«Полный стадион народа — время начинать матч». Объявим об открытии встречи официально — в главном классе приложения:

Как видите, ничего зубодробительного здесь нет. Это пока только введение в многопоточность, но вы уже представляете, как это работает, и можете экспериментировать — ограничивать длительность игры не числом ударов, а по времени, например. Мы ещё вернёмся к теме многопоточности — рассмотрим пакет java.util.concurrent, библиотеку Akka и механизм volatile. А еще поговорим о реализации многопоточности на Python.

Что такое мьютекс java. Смотреть фото Что такое мьютекс java. Смотреть картинку Что такое мьютекс java. Картинка про Что такое мьютекс java. Фото Что такое мьютекс java

Какая тема вызывает больше всего вопросов и затруднений у начинающих? Когда я спросила об этом преподавателя и Java-программиста Александра Пряхина, он сразу ответил: «Многопоточность». Спасибо ему за идею и помощь в подготовке этой статьи!

Мы заглянем во внутренний мир приложения и его процессов, разберёмся, в чём суть многопоточности, когда она полезна и как её реализовать — на примере Java. Если учите другой язык ООП, не огорчайтесь: базовые принципы одни и те же.

О потоках и их истоках

Чтобы понять многопоточность, сначала вникнем, что такое процесс. Процесс – это часть виртуальной памяти и ресурсов, которую ОС выделяет для выполнения программы. Если открыть несколько экземпляров одного приложения, под каждый система выделит по процессу. В современных браузерах за каждую вкладку может отвечать отдельный процесс.

Вы наверняка сталкивались с «Диспетчером задач» Windows (в Linux это — «Системный монитор») и знаете, что лишние запущенные процессы грузят систему, а самые «тяжёлые» из них часто зависают, так что их приходится завершать принудительно.

Но пользователи любят многозадачность: хлебом не корми — дай открыть с десяток окон и попрыгать туда-сюда. Налицо дилемма: нужно обеспечить одновременную работу приложений и при этом снизить нагрузку на систему, чтобы она не тормозила. Допустим, «железу» не угнаться за потребностями владельцев — нужно решать вопрос на программном уровне.

Мы хотим, чтобы в единицу времени процессор успевал выполнить больше команд и обработать больше данных. То есть нам надо уместить в каждом кванте времени больше выполненного кода. Представьте единицу выполнения кода в виде объекта — это и есть поток.

К сложному делу легче подступиться, если разбить его на несколько простых. Так и при работе с памятью: «тяжёлый» процесс делят на потоки, которые занимают меньше ресурсов и скорее доносят код до вычислителя (как именно — см. ниже).

У каждого приложения есть как минимум один процесс, а у каждого процесса — минимум один поток, который называют главным и из которого при необходимости запускают новые.

Разница между потоками и процессами

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

Процессы работают каждый со своими данными — обмениваться чем-то они могут только через механизм межпроцессного взаимодействия. Потоки обращаются к данным и ресурсам друг друга напрямую: что изменил один — сразу доступно всем. Поток может контролировать «собратьев» по процессу, в то время как процесс контролирует исключительно своих «дочек». Поэтому переключаться между потоками быстрее и коммуникация между ними организована проще.

Какой отсюда вывод? Если вам нужно как можно быстрее обработать большой объём данных, разбейте его на куски, которые можно обрабатывать отдельными потоками, а затем соберите результат воедино. Это лучше, чем плодить жадные до ресурсов процессы.

Но почему такое популярное приложение как Firefox идёт по пути создания нескольких процессов? Потому что именно для браузера изолированная работа вкладок — это надёжно и гибко. Если с одним процессом что-то не так, не обязательно завершать программу целиком — есть возможность сохранить хотя бы часть данных.

Что такое многопоточность

Вот мы и подошли к главному. Многопоточность — это когда процесс приложения разбит на потоки, которые параллельно — в одну единицу времени — обрабатываются процессором.

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

Многопоточные приложения можно запускать и на одноядерных процессорах, но тогда потоки выполняются по очереди: первый поработал, его состояние сохранили — дали поработать второму, сохранили — вернулись к первому или запустили третий, и т.д.

Что такое мьютекс java. Смотреть фото Что такое мьютекс java. Смотреть картинку Что такое мьютекс java. Картинка про Что такое мьютекс java. Фото Что такое мьютекс java

Занятые люди жалуются, что у них всего две руки. Процессы и программы могут иметь столько рук, сколько нужно для скорейшего выполнения задачи.

Жди сигнала: синхронизация в многопоточных приложениях

Представьте, что несколько потоков пытаются одновременно изменить одну и ту же область данных. Чьи изменения будут в итоге приняты, а чьи — отменены? Чтобы работа с общими ресурсами не приводила к путанице, потокам нужно координировать свои действия. Для этого они обмениваются информацией с помощью сигналов. Каждый поток сообщает другим, что он сейчас делает и каких изменений ждать. Так данные всех потоков о текущем состоянии ресурсов синхронизируются.

В категориях объектно-ориентированного программирования сигналы — это объекты синхронизации. У каждого из них — своя роль во взаимодействии.

Основные средства синхронизации

Взаимоисключение (mutual exclusion, сокращённо — mutex) — «флажок», переходящий к потоку, который в данный момент имеет право работать с общими ресурсами. Исключает доступ остальных потоков к занятому участку памяти. Мьютексов в приложении может быть несколько, и они могут разделяться между процессами. Есть подвох: mutex заставляет приложение каждый раз обращаться к ядру операционной системы, что накладно.

Семафор — позволяет вам ограничить число потоков, имеющих доступ к ресурсу в конкретный момент. Так вы снизите нагрузку на процессор при выполнении кода, где есть узкие места. Проблема в том, что оптимальное число потоков зависит от машины пользователя.

Событие — вы определяете условие, при наступлении которого управление передаётся нужному потоку. Данными о событиях потоки обмениваются, чтобы развивать и логически продолжать действия друг друга. Один получил данные, другой проверил их корректность, третий — сохранил на жёсткий диск. События различаются по способу отмены сигнала о них. Если нужно уведомить о событии несколько потоков, для остановки сигнала придётся вручную ставить функцию отмены. Если же целевой поток только один, можно создать событие с автоматическим сбросом. Оно само остановит сигнал, после того как он дойдёт до потока. Для гибкого управления потоками события можно выстраивать в очередь.

Критическая секция — более сложный механизм, который объединяет в себе счётчик цикла и семафор. Счётчик позволяет отложить запуск семафора на нужное время. Преимущество в том, что ядро задействуется лишь в случае, если секция занята и нужно включать семафор. В остальное время поток выполняется в пользовательском режиме. Увы, секцию можно использовать только внутри одного процесса.

Как реализовать многопоточность в Java

За работу с потоками в Java отвечает класс Thread. Создать новый поток для выполнения задачи — значит создать экземпляр класса Thread и связать его с нужным кодом. Сделать это можно двумя путями:

образовать от Thread подкласс;

имплементировать в своём классе интерфейс Runnable, после чего передавать экземпляры класса в конструктор Thread.

Пока мы не будем затрагивать тему тупиковых ситуаций (deadlock’ов), когда потоки блокируют работу друг друга и зависают — оставим это для следующей статьи. А сейчас перейдём к практике.

Пример многопоточности в Java: пинг-понг мьютексами

Если вы думаете, что сейчас будет что-то страшное — выдохните. Работу с объектами синхронизации мы рассмотрим почти в игровой форме: два потока будут перебрасываться mutex’ом. Но по сути вы увидите реальное приложение, где в один момент времени только один поток может обрабатывать общедоступные данные.

Сначала создадим класс, наследующий свойства уже известного нам Thread, и напишем метод «удара по мячу» (kickBall):

Теперь позаботимся о мячике. Будет он у нас не простой, а памятливый: чтоб мог рассказать, кто по нему ударил, с какой стороны и сколько раз. Для этого используем mutex: он будет собирать информацию о работе каждого из потоков — это позволит изолированным потокам общаться друг с другом. После 15-го удара выведем мяч из игры, чтоб его сильно не травмировать.

А теперь на сцену выходят два потока-игрока. Назовём их, не мудрствуя лукаво, Пинг и Понг:

«Полный стадион народа — время начинать матч». Объявим об открытии встречи официально — в главном классе приложения:

Источник

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *