Студопедия  
Главная страница | Контакты | Случайная страница

АвтомобилиАстрономияБиологияГеографияДом и садДругие языкиДругоеИнформатика
ИсторияКультураЛитератураЛогикаМатематикаМедицинаМеталлургияМеханика
ОбразованиеОхрана трудаПедагогикаПолитикаПравоПсихологияРелигияРиторика
СоциологияСпортСтроительствоТехнологияТуризмФизикаФилософияФинансы
ХимияЧерчениеЭкологияЭкономикаЭлектроника

Когда процессов слишком много

Читайте также:
  1. E. Многокутник
  2. III. Вожди дороже нам вдвойне, когда они уже в стене
  3. III. Недостатки в развитии познавательных процессов.
  4. Model Explorer - навигатор модели процессов
  5. OSV: Работал когда-то в Соединенных Штатах Америки (а конкретно — в городе Феникс, штат Аризона) один известный и очень действенный гипнотизер по имениМилтон Эриксон.
  6. Oгранка многогранников
  7. The knowledge of all fabricating processes is necessary for a processing engineer. (Знание всех процессов обработки необходимо для инженера-технолога)
  8. V.3.I. Когда и как цитируют: десять правил
  9. VI. Господь лихую шутку учинил, когда сюжет еврея сочинил
  10. А вот можно личный вопрос? – Конечно. А вы когда-нибудь сами верили в судьбу?

В некоторый момент вы увидите, что ColorBoxes совсем увяз в выполнении. На моей машине это возникало примерно после таблицы 10х10. Но почему такое происходит? Вы подозрительны если считаете, что возможно Swing может что-то творить с этим, так что, вот пример, который проверяет данное утверждение путем создания небольшого количества процессов. Следующий исходный код переделан так, чтобы ArrayList реализует Runnable и данный ArrayList содержит номера цветовых блоков и случайным образом выбирает один для обновления. В результате мы имеем гораздо меньше процессов, чем цветовых блоков, так что при увеличении скорости выполнения мы знаем, что это именно из-за гораздо меньшего количества процессов по сравнению с предыдущим примером:

//: c14:ColorBoxes2.java// Balancing thread use.// <applet code=ColorBoxes2 width=600 height=500>// <param name=grid value="12">// <param name=pause value="50">// </applet>import javax.swing.*;import java.awt.*;import java.awt.event.*;import java.util.*;import com.bruceeckel.swing.*; class CBox2 extends JPanel { private static final Color[] colors = { Color.black, Color.blue, Color.cyan, Color.darkGray, Color.gray, Color.green, Color.lightGray, Color.magenta, Color.orange, Color.pink, Color.red, Color.white, Color.yellow }; private Color cColor = newColor(); private static final Color newColor() { return colors[ (int)(Math.random() * colors.length) ]; } void nextColor() { cColor = newColor(); repaint(); } public void paintComponent(Graphics g) { super.paintComponent(g); g.setColor(cColor); Dimension s = getSize(); g.fillRect(0, 0, s.width, s.height); }} class CBoxList extends ArrayList implements Runnable { private Thread t; private int pause; public CBoxList(int pause) { this.pause = pause; t = new Thread(this); } public void go() { t.start(); } public void run() { while(true) { int i = (int)(Math.random() * size()); ((CBox2)get(i)).nextColor(); try { t.sleep(pause); } catch(InterruptedException e) { System.err.println("Interrupted"); } } } public Object last() { return get(size() - 1);}} public class ColorBoxes2 extends JApplet { private boolean isApplet = true; private int grid = 12; // Shorter default pause than ColorBoxes: private int pause = 50; private CBoxList[] v; public void init() { // Get parameters from Web page: if (isApplet) { String gsize = getParameter("grid"); if(gsize!= null) grid = Integer.parseInt(gsize); String pse = getParameter("pause"); if(pse!= null) pause = Integer.parseInt(pse); } Container cp = getContentPane(); cp.setLayout(new GridLayout(grid, grid)); v = new CBoxList[grid]; for(int i = 0; i < grid; i++) v[i] = new CBoxList(pause); for (int i = 0; i < grid * grid; i++) { v[i % grid].add(new CBox2()); cp.add((CBox2)v[i % grid].last()); } for(int i = 0; i < grid; i++) v[i].go(); } public static void main(String[] args) { ColorBoxes2 applet = new ColorBoxes2(); applet.isApplet = false; if(args.length > 0) applet.grid = Integer.parseInt(args[0]); if(args.length > 1) applet.pause = Integer.parseInt(args[1]); Console.run(applet, 500, 400); }} ///:~

В ColorBoxes2 создается массив CBoxList и инициализируется для хранения grid CBoxList, каждый из которых знает на сколько долго необходимо засыпать. Затем в каждый CBoxList добавляется аналогичное количество объектов CBox2 и каждый список вызывает go(), что запускает процесс.

CBox2 аналогичен CBox: он рисует себя произвольно выбранным цветом. Но это и все что CBox2 делает. Вся работа с процессами теперь перемещена в CBoxList.

CBoxList также может иметь унаследованный Thread и иметь объект член типа ArrayList. Данное решение имеет преимущества в том, что методам add() и get() затем может быть передан особый аргумент и возвращаемое значение, вместо общих Object 'ов. (И их имя также может быть изменено на что-то более кортокое.) На первый взгляд кажется, что приведенном здесь пример требует меньше кодирования. Дополнительно, он автоматически сохраняет все функции выполняемые ArrayList. Со всеми приведениями и скобками, необходимыми для get() это не будет выходом при росте основного кода программы.

Как и прежде, при реализации Runnable вы не получаете все, что предоставляется вместе с Thread, так что вам необходимо создать новый Thread и самим определить его конструктор, чтобы иметь что-либо для start(), так, как это было сделано в конструкторе CBosList и в go(). Метод run() просто выбирает случайны номер элемента в листе и вызывает nextCollor() для этого элемента, чтобы он применил новый, солучайно выбранный цвет.

Во время работы этой программы можно видеть, что она действительно выполняется быстрее и быстрее реагирует на действия (например, при попытке завершения все происходит намного быстрее), и похоже, она не затормаживается при бОльших размерах таблицы. Таким образом, в уравнение процессов был добавлен новый фактор: вы должны быть наблюдательны, чтобы заметить, что у вас не "слишком много процессов" (чтобы это не означало в вашем конкретной программе или платформе, как например в нашем случае, ColorBoxes имеет только один процесс, который ответственен за всю перерисовку, что приводит к снижению производительности из-за слишком большого количества запросов). Если у вас слишком много процессов, то можно попробовать использовать одну из техник приведенных выше для "балансировки" количества процессов в вашей программе. Если наблюдается проблема с производительностью в программе с множеством процессов, то необходимо проверить следующее:

  1. Достаточно ли у вас вызовов sleep(), yield(), и/или wait()?
  2. Насколько продолжителен вызов sleep()?
  3. Запустили ли вы слишком много процессов?
  4. Пробовали ли вы различные платформы и JVM?

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

Резюме

Крайне необходимо выучить, когда необходимо использовать множество процессов и когда можно избежать этого. Основная причина их использования заключается в возможности управления несколькими задачами, смешивание которых приводит к более эффективному использованию компьютера (включая возможность прозрачно распределять задачи между несколькими процессорами) или к удобству пользователя. Классический пример использования ресурсов - это использование процессора во время ожидания операций ввода/вывода. Классический пример удобства для пользователя - это опрос кнопки "stop" во время продолжительного копирования.

Основные же недостатки процессов следующие:

  1. Падение производительности при ожидании использования общего ресурса
  2. Требуются дополнительные ресурсы процессора (CPU) для управления процессами
  3. Непомерная сложность, из-за глупой идеи создать еще один процесса для обновления каждого элемента в массиве
  4. Патологии, включающие нехватку ресурсов (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.




Дата добавления: 2015-09-11; просмотров: 19 | Поможем написать вашу работу | Нарушение авторских прав

Неправильный доступ к ресурсам | Синхронизация счетчиков | Повторное обращение к JavaBeans | Установка блокировки | Ожидание и уведомление | Тестирование | Запрещение stop( ), suspend( ), resume( ), и destroy( ) в Java 2 | Чтение и установка приоритетов | Группы процессов | Управление группами процессов |


lektsii.net - Лекции.Нет - 2014-2024 год. (0.008 сек.) Все материалы представленные на сайте исключительно с целью ознакомления читателями и не преследуют коммерческих целей или нарушение авторских прав