Иллюстрированный самоучитель по Java

Подпроцессы

Основное понятие современных операционных систем – процесс (process). Как и все общие понятия, процесс трудно определить, да это и не входит в задачу книги. Можно понимать под процессом выполняющуюся (runnable) программу, но надо помнить о том, что у процесса есть несколько состояний. Процесс может в любой момент перейти к выполнению машинного кода другой программы, а также "заснуть" (sleep) на некоторое время, приостановив выполнение программы. Он может быть выгружен на диск. Количество состояний процесса и их особенности зависят от операционной системы.

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

Если на компьютере только один процессор, то он переключается с одного процесса на другой, создавая видимость одновременной работы. Переключение происходит по истечении одного или нескольких "тиков" (ticks). Размер тика зависит от тактовой частоты процессора и обычно имеет порядок 0.01 секунды. Процессам назначаются разные приоритеты (priority). Процессы с низким приоритетом не могут прервать выполнение процесса с более высоким приоритетом, они меньше занимают процессор и поэтому выполняются медленно, как говорят, "на фоне". Самый высокий приоритет у системных процессов, например, у диспетчера (scheduler), который как раз и занимается переключением процессора с процесса на процесс. Такие процессы нельзя прерывать, пока они не закончат работу, иначе компьютер быстро придет в хаотическое состояние.

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

В эту же область записывается часть сведений о процессе, составляющая его контекст (context). Очень важно разделить адресные пространства разных процессов, чтобы они не могли изменить код и данные друг друга. Операционные системы по-разному относятся к обеспечению защиты адресных пространств процессов. MS Windows NT/2000 тщательно разделяют адресные пространства, тратя на это много ресурсов и времени. Это повышает надежность выполнения программы, но затрудняет создание процесса. Такие операционные системы плохо справляются с управлением большого числа процессов.

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

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

Работу многозадачной системы можно упростить и ускорить, если разрешить взаимодействующим процессам работать в одном адресном пространстве. Такие процессы называются threads. В русской литературе предлагаются различные переводы этого слова. Буквальный перевод – "нить", но мы не занимаемся прядильным производством. Часто переводят thread как "поток", но в этой книге мы говорим о потоке ввода/вывода. Иногда просто говорят "тред", но в русском языке уже есть "тред-юнион". Встречается перевод "легковесный процесс", но в некоторых операционных системах, например, Solaris, есть и thread и lightweight process. Остановимся на слове "подпроцесс".

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

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

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

Подпроцесс в Java создается и управляется методами класса Thread. После создания объекта этого класса одним из его конструкторов новый подпроцесс запускается методом start ().

Получить ссылку на текущий подпроцесс можно статическим методом:

Thread.currentThread();

Класс Thread реализует интерфейс Runnable. Этот интерфейс описывает только один метод run(). Новый подпроцесс будет выполнять то, что записано в этом методе. Впрочем, класс Thread содержит только пустую реализацию метода run (), поэтому класс Thread не используется сам по себе, он всегда расширяется. При его расширении метод run() переопределяется.

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

Итак, задать действия создаваемого подпроцесса можно двумя способами: расширить класс Thread или реализовать интерфейс Runnable. Первый способ позволяет использовать методы класса Thread для управления подпроцессом. Второй способ применяется в тех случаях, когда надо только реализовать метод run(), или класс, создающий подпроцесс, уже расширяет какой-то другой класс.

Посмотрим, какие конструкторы и методы содержит класс Thread.

Если Вы заметили ошибку, выделите, пожалуйста, необходимый текст и нажмите CTRL + Enter, чтобы сообщить об этом редактору.