[JAVA] Многоядерные архитектуры нужны не только для игр

Автор: Фрунт Андрей
09.11.2009 16:38

Любой разработчик, который работает с оконным интерфейсом (по сути, пусть даже и консольным) знает, каким минусом могут стать задачи, которые требуют сколько-нибудь существенной вычислительной работы. Это касается как длительный циклов, так и действий по отображению объектных структур на структуры БД (ORM), которое я рассматриваю в своем цикле статей, и т.д.

 

Дело в том, что различные "умные" авторы книг (обычно, наши, СНГшные) всячески пытаются уберечь от многопоточности своих читатей, чем демонстрируют пробелы в своем же спец. образовании. На самом же деле, многопоточность - это инструмент, который в умелых руках способен прибавить приложениям как кажущейся, так и реальной производительности.

 

Как обычно пишутся программы с GUI в первом приближении? Обработчик события вызывает определенные функции, ждёт их завершения, блокируя интерфейс, и возвращает управление в поток обработки событий интерфейса (Event Dispathcer Thread, EDT). В этом случае, вся программа выполняется в рамках этого потока и, при выполнении на многоядерном процессоре, на основоном ядре, а остальные "гуляют".

 

Но зачем же нам тогда многоядерные и многопроцессорные архитектуры в рамках рабочей станции? Самое время задуматься о многопоточном выполнении операций.

 

Самая обыденная задача - получение результатов выборки из БД и отображение их в GUI. Если данных не много, а приложение выполняется на той же машине, на которой функционирует СУБД, то проблем и так не возникает. Но представьте себе ситуацию, когда результирующие данные составляют 1-2 Мб, после получения преобразуются какой-нибудь ORM-библиотекой, а проводящей средой является Ethernet или, еще хуже, Wi-Fi (54Mbit/s). Вот здесь мы и получим блокирование интерфейса на несколько секунд.

 

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

 

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

 

Такой подход имеет несколько преимуществ:

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

 

Здесь нужно сделать некоторые замечания. Раньше JAVA не очень хорошо умела распараллеливать свои потоки, сейчас же все иначе - многопоточный подход может дать вам, в большинстве случаев, двойную производительность (если есть двуядерный процессор) и даже утроенную-учетверенную производительность в случае использования 4-ядерной архитектуры. Насчет 2-ядерников все понятно, но, если вы хотите насладится многопоточностью на 4-ядернике, то нужно применять вложенные потоки или же независимые одновременные потоки, которые отвечают за разную логику программы. Однако же, такое усложнение может привести к неоправданному усложнению кода, так что выбирайте сами.

 

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

 

Насчет JAVA могу посоветовать почаще использовать SwingWorker вместо обычного подхода в виде связки Thread+Runnable, потому что SwingWorker дает несколько важных преимуществ, самым главным из которых является поствыполнение необходимых действий в вызвавшем потоке.

Обновлено 09.11.2009 18:36

 

Комментарии  

 
#1 Гость 09.11.2009 18:06
спасибо за полезную информацию :)
Цитировать
 

Добавить комментарий


Защитный код
Обновить