Крайне необходимо выучить, когда необходимо
Крайне необходимо выучить, когда необходимо использоватьмножество процессов и когда можно избежать этого. Основная причина их использования заключается в возможности управления несколькими задачами, смешивание которых приводит к более эффективному использованию компьютера (включая возможность прозрачно распределять задачи между несколькими процессорами) или к удобству пользователя. Классический пример использования ресурсов - это использование процессора во время ожидания операций ввода/вывода. Классический пример удобства для пользователя - это опрос кнопки "stop" во время продолжительного копирования.
Основные же недостатки процессов следующие:
Падение производительности при ожидании использования общего ресурса
Требуются дополнительные ресурсы процессора (CPU) для управления процессами
Непомерная сложность, из-за глупой идеи создать еще один процесса для обновления каждого элемента в массиве
Патологии, включающие нехватку ресурсов (starving), разность в скорости выполнения (racing) и мертвые блокировки (deadlock)
Дополнительное превосходство процессов в том, что они заменяют "тяжелое" переключение контекста приложения (в пересчете на 100 инструкций) на "легкое" переключение контекста выполнения (в пересчете на 100 инструкций). Поскольку все процессы в данном приложении разделяют одно и то же адресное пространство, то легкое переключение контекста изменяет только выполнение программы и локальные переменные. С другой стороны, изменение приложения - тяжелое переключение контекста - должно поменять всю память.
Использование процессов схоже с шагом в совершенно иной мир и изучение совершенно нового языка программирования, или, по крайне мере, новой концепции языка. С появление поддержки процессов в большинстве операционных систем микрокомпьютеров, расширения для процессов также появились в языках программирования или библиотеках. В любом случае, программирование процессов выглядит мистикой (1) и требует смещения в способе понимания программирования: и (2) выглядит похожей на реализацию поддержки процессов в других языках программирования, таким образом, если вы поймете процессы, вы поймете и большинство языков. И хотя поддержка процессов может сделать Java похожей на достаточно трудный язык программирования, Java в этом не виновата. Процессы слишком хитрые.
Наибольшее затруднение с процессами возникает из- за того, что более чем один процесс может использовать ресурсы - такие как память в объектах - и необходимо быть уверенным, что несколько процессов не пытаются прочитать и изменить данные в один и тот же момент. Это требует рассудительного использования ключевого слова synchronized, которое является весьма полезным, но должно быть тщательно понято, так как может незаметно привести к ситуациям с мертвой блокировкой.
В дополнении, приложение с процессами является в какой-то степени искусством. Теоретически Java создавалась для возможности создания такого количества объектов сколько необходимо для решения стоЯщей проблемы. (Хотя создание нескольких миллионов объектов для инженерного анализа конечного множества, например, вряд ли будет практично на Java.) Однако похоже, что существует верхняя граница количеству процессов, которые возможно создать в приложении, поскольку с определнной точки наличие большего количества процессов приложение становится громоздким. Эта критическая точки исчисляется не несколькими тысячами, как это может быть с объектами, а всего лишь парой сотен, иногда даже менее 100. Поскольку в большинстве случаев создается только процессы для решения проблемы, то обычно их количество не превышает установленный лимит, даже в большинстве главных приложений их количество невелико.
Существенный, не интуитивный момент с процессами заключается в том, что поскольку процессы управляются планировщиком, то можно достаточно просто заставить приложение выполняться быстрее поместив вызов sleep() внутри основного цикла в теле run(). Это определнно делает все это похожим на искусство, в особенности, когда продолжительная пауза увеличивает скорость выполнения. Конечно, причина здесь в том, что более короткие задержки могут стать причиной того, что прерывания планировщика в конце sleep() произойдет до того, как выполняемый процесс готов заснуть, заставляя планировщик все остановить и возобновить выполнение того, что должно было быть сделано, позднее и только затем перейти в спячку. Это дает дополнительные размышления для понимания того, какое месиво может получиться.
Стоит обратить внимание на одну вещь, которая пропущена в данной главе, пример с анимацией, что является одной из популярнейших приложений для апплетов. Однако, полное решение этой задачи (со звуком) представлено в Java JDK (доступном на java.sun.com) в разделе примеров. В дополнение можно ожидать лучшей поддержки анимации, что станет частью будущих версий Java, несмотря на то, что появляются полностью различные, не-Java, без необходимости программирования решения для анимации в Web, которые вероятно будут лучше традиционных решений. Для понимания того, как работает анимации в Java можно прочитать Core Java 2 от Horstmann & Cornell, Prentice-Hall, 1997. За дополнительным объяснением процессов смотрите Concurrent Programming in Java написанную Doug Lea, Addison-Wesley, 1997, или Java Threads от Oaks & Wong, O'Reilly, 1997.