Многопоточность в Java

Это – перевод статьи “Threading in Java” автора Beka Kodirov. Вторая часть статьи находится здесь.

Чем отличается поток от процесса?

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

  • PID – уникальный идентификатор процесса
  • PPID – идентификатор родительского процесса
  • UID – идентификатор пользователя
  • Heap – пространство памяти, выделенное для данного процесса. Каждый процесс обладает собственным пространством.

По умолчанию каждый процесс содержит минимум один поток (обычно main- или ui-). Как только все потоки завершаются, процесс уничтожается. Процесс может иметь множество потоков, но поток может принадлежать только одному процессу.

Потоки могут работать с общими участками памяти, то есть одновременно использовать один и тот же объект. Области памяти процессов не пересекаются, то есть они не могут использовать один и тот же участок RAM.

Все потоки в Java являются нативными Linux-потоками или т. н.pthreads. Поток принадлежит процессу, в котором он был создан.

Сравните совместную и вытесняющую многозадачность

Существует несколько типов многозадачности – невытесняющая, совместная, вытесняющая.

Совместная многозадачность

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

Вытесняющая многозадачность

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

Что такое “Green Threads” и есть ли они в Java (HotSpot JVM 7)?

В Java был добавлен новый тип потоков, названный “зелёный поток”. Он имитирует native поток, то есть за весь жизненный цикл зелёного потока и переключение между ними отвечает JVM, а не ядро операционной системы.

Но есть и недостатки. Самый значительный – невозможность выполнения одновременно двух потоков. Так как native поток всего один, даже если используется несколько процессоров и множество зелёных потоков, выполнять такой поток сможет только один ЦПУ.

Что такое планировщик потоков? Какой алгоритм он использует?

В системе, где одновременно работают несколько приложений, должен быть планировщик. Чтобы пользователь мог почувствовать всю мощь параллельного выполнения, ресурсы процессора должны распределяться между потоками разных приложений и именно это находится в зоне ответственности планировщика. Он решает какой поток запустить и как долго его выполнять. Стратегии планирования могут меняться, но обычно все они основываются на приоритете: поток с более высоким приоритетом получает ресурсы раньше, чем они достаются более “низкому” потоку. В Java приоритет потоков может иметь значение от 1 (самый низкий) до 10 (самый высокий). Приоритет по умолчанию равен 5.

Каковы преимущества многопоточности в однопроцессорных системах?

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

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