Что такое тема?

Приложение Java работает на виртуальной машине (JVM). JVM - это процесс, который имеет доступ к системным ресурсам, таким как ЦП, ОЗУ, файловая система и другие компоненты оборудования - любезно ОС. Многие потоки могут выполняться внутри процесса. Потоки можно рассматривать как легковесные процессы.

Поток отвечает за выполнение программных инструкций в ЦП; использование памяти стека для хранения локальных переменных и параметров. В каждом приложении есть хотя бы один поток - основной.

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

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

Однопоточное и многопоточное выполнение

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

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

Допустим, у нас есть элементарное приложение для анализа журналов, которое должно выполнять поиск в больших файлах журналов приложений на основе пользовательского запроса.

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

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

- Разделяй и властвуй!

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

Межпоточное общение

Каждый поток работает в собственном пространстве памяти. Связь между потоками достигается через объект в куче; поскольку объекты в куче доступны всем потокам.

Зачем приложению нужно, чтобы потоки взаимодействовали друг с другом? Рассмотрим следующий вариант использования (надуманный):

Проблемные государственные деятели t

* Печатать числа от 1, 2, 3 до 20 по порядку.
* Нечетные числа должны печататься в нечетной цепочке
* Четные числа должны печататься в четной цепочке

Пример вывода

OddThread: 1
EvenThread: 2
OddThread: 3
EvenThread: 4
.
.
OddThread: 19
EvenThread: 20

Ограничение
Если 2 потока не взаимодействуют друг с другом, эта задача не может быть выполнена. (Эй, кто-нибудь производитель-потребитель ?!)

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

Решите проблему перед тем, как приступить к реализации - анонимный, но дельный совет!

  1. Создайте два потока - Нечетный поток и Четный поток. Спасибо ядрам ЦП!
  2. Четный поток должен начать выполнение только после того, как нечетный поток напечатает номер 1. Спасибо CountDownLatch (1)!
  3. После печати 1 нечетный поток должен передать управление четному потоку, прежде чем приступить к печати следующего числа, и наоборот. Благодаря API синхронизации - wait () и notify ()!
    - Мы будем использовать объект блокировки, через который потоки обмениваются данными, т.е. передают управление после печати числа
    - Вызов уведомить о блокировке после печати числа, чтобы другой поток проснулся и был готов к его планированию для выполнения
    - После этого вызовите ожидание для объекта блокировки, чтобы текущий поток мог быть приостановлен, а другой поток мог получить блокировка
    - Цикл, который печатает числа в каждом потоке, должен быть заблокирован путем синхронизации на общем объекте блокировки. Без предварительного получения блокировки методы ожидания и уведомления не могут быть вызваны для объекта блокировки.

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

Реализация

Примечание

  1. Код можно улучшить, используя блокировку из пакета java.util.concurrent.Locks.
  2. Из-за прерываний и ложных пробуждений у object.wait () есть неотъемлемый риск, связанный с ним. Поэтому рекомендуется вызывать wait () внутри цикла, проверяя, выполнено ли условие ожидания. - "Ссылка"

Можете ли вы попробовать запустить приведенный выше код и посмотреть, печатает ли он ожидаемый результат. Также проверьте, завершается ли программа после печати вывода. Если нет, можете ли вы это исправить?

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

Спасибо за прочтение! :)