<?xml version="1.0"?>
<?xml-stylesheet type="text/css" href="http://wiki.linuxformat.ru/wiki/skins/common/feed.css?303"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="ru">
		<id>http://wiki.linuxformat.ru/wiki/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Skryabin+yuri</id>
		<title>Linuxformat - Вклад участника [ru]</title>
		<link rel="self" type="application/atom+xml" href="http://wiki.linuxformat.ru/wiki/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Skryabin+yuri"/>
		<link rel="alternate" type="text/html" href="http://wiki.linuxformat.ru/wiki/%D0%A1%D0%BB%D1%83%D0%B6%D0%B5%D0%B1%D0%BD%D0%B0%D1%8F:Contributions/Skryabin_yuri"/>
		<updated>2026-05-13T11:53:30Z</updated>
		<subtitle>Вклад участника</subtitle>
		<generator>MediaWiki 1.19.20+dfsg-0+deb7u3</generator>

	<entry>
		<id>http://wiki.linuxformat.ru/wiki/LXF84:Opera_9</id>
		<title>LXF84:Opera 9</title>
		<link rel="alternate" type="text/html" href="http://wiki.linuxformat.ru/wiki/LXF84:Opera_9"/>
				<updated>2008-04-04T06:36:44Z</updated>
		
		<summary type="html">&lt;p&gt;Skryabin yuri: Текст&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Opera 9 ==&lt;br /&gt;
''Песенка коммерческой Opera уже спета, но шоу, тем не менее, продолжается.&lt;br /&gt;
'''Ричард Коббетт''' разбирается в деталях.''&lt;br /&gt;
&lt;br /&gt;
{{врезка|Ширина=200px|left|&lt;br /&gt;
Заголовок=Вкратце...|&lt;br /&gt;
Содержание=Новейшая версия комплекта Opera &amp;quot;все-в-одном&amp;quot;, с виджетами и поддержкой BitTorrent, &lt;br /&gt;
по-прежнему отличается высокой скоростью.}}&lt;br /&gt;
[[Image:Img_84_00_0.png|thumb|300px|Все, что нужно от браузера, если не вообще все, что нужно – добавка новой системы виджетов к прежде неизменной линейке Opera.]]&lt;br /&gt;
Вы жалели Opera. Не потому, что он остался в стороне от титанической схватки между Explorer и Firefox, и даже не потому, что это достойный претендент, так и не дождавшийся своего часа. А потому, что нет другого браузера с такой богатой историей первопроходца в самых крутых вещах — от жестов мышью до вкладок и ээ… Greasemonkey (хотя в Opera это уныло называлось User JS, потому-то он и не взлетел) — и тем не менее его вспоминают всего лишь как «браузер с баннерами».&lt;br /&gt;
&lt;br /&gt;
Все, хватит. Теперь Opera 9 бесплатен, освобожден от прежних рекламных и лицензионных ключей, готов к действию. И вот вам факт — «на выходе из коробки» это самый вылизанный и функциональный браузер из&lt;br /&gt;
имеющихся. Пользоваться Opera не только просто, но и приятно. До всего, что вам нужно, дотянетесь мышью, и нет нужды ни в каких расширениях. Это полный web-пакет, справляющийся и с простейшим Интернет-серфингом, и с почтой (IMAP и POP3).&lt;br /&gt;
&lt;br /&gt;
Звучит неплохо? Да. Но есть и недостатки. Если сайт построен в духе любимых Дэвидом Картрайтом [David Cartwright] web-стандартов, то проблем не возникнет — Opera 9 проходит тест Acid2 и превосходно обрабатывает большинство статических страниц. Но вот многие сайты на Ajax, созданные и тестированные&lt;br /&gt;
эксклюзивно под IE и Firefox — другое дело. Google Calendar более-менее совместим, но все еще отмечает Opera как неподдерживаемый браузер, а динамические ссылки в инструменте online-заметок Backpack ломаются. Может быть, посещаемых именно вами сайтов проблемы и не касаются — но некоторые страницы просто не работают.&lt;br /&gt;
&lt;br /&gt;
Web-разработчикам, конечно, жить стало легче: встроенные таблицы стилей позволяют посмотреть, как страничка будет выглядеть на экране мобильного устройства, без таблицы стилей или в «сыром» текстовом формате. Можно провести валидацию одним нажатием клавиши, а если вы подготовили подходящую презентацию, используйте Opera как инструмент для слайд-шоу.&lt;br /&gt;
&lt;br /&gt;
=== Быстрее всех ===&lt;br /&gt;
{{врезка|Ширина=200px|left|&lt;br /&gt;
Заголовок=Грэм считает...|&lt;br /&gt;
Содержание=«Все мы любим Opera, но она предлагает недостаточно, чтобы превзойти способности&lt;br /&gt;
Firefox или живую многоплановость Konqueror».}}&lt;br /&gt;
&lt;br /&gt;
{{врезка|Ширина=200px|left|&lt;br /&gt;
Заголовок=Свойства навскидку|&lt;br /&gt;
Содержание=&lt;br /&gt;
*BitTorrent&lt;br /&gt;
[[Image:Img_84_00_0.png|thumb|Загрузка через встроенный BitTorrent стремительна, как падение с дерева.]]&lt;br /&gt;
*Виджеты&lt;br /&gt;
[[Image:Img_84_00_0.png|thumb|Виджеты кросс-платформенные, хотя на Linux наблюдаются некоторые графические проблемы.]]&lt;br /&gt;
}}&lt;br /&gt;
В скорости Opera равных нет, если говорить о рендеринге страниц и времясберегающих функциях движка. Потребление памяти в нашем тесте составило 28 МБ — меньше, чем Firefox и Epiphany (оба потянули на&lt;br /&gt;
32 МБ). Усиленно рекламируемой на сайте Opera голосовой системы управления пока нет, но легкость доступа ко всем инструментам, и множество клавиатурных комбинаций делают эту нехватку несущественной. Один из самых полезных инструментов — диалоговое окно Site Preferences (Параметры сайтов), в котором можно отключить навязчивые cookies и встроенные фреймы или настроить обработку «правого» щелчка мыши, а также добавить собственную таблицу стилей или файл JavaScript, чтобы изменить поведение страницы.&lt;br /&gt;
&lt;br /&gt;
Наиболее значительное дополнение — система виджетов (Widget). При работе Opera виджеты порхают друг над другом и над рабочим столом, и установка любого из них — дело одного щелчка. Не удивительно, что поисковый инструмент BitTorrent расположен выше всех; сразу за ним следуют напоминания и простые игры — их несложно создать, и они кросс-платформенны.&lt;br /&gt;
&lt;br /&gt;
У Opera остались проблемы с просмотром web-сайтов, и вариант «все-в-одном» не похож на Firefox с миллионом расширений. Но это совершенно иной стиль браузера, при котором все инструменты работают совместно, а не явились со всех концов сети, и тут есть свои преимущества. Виджеты — превосходное дополнение, а солидный самостоятельный браузер позволяет немедленно окунуться в Сеть с головой.&lt;br /&gt;
{{врезка|Ширина=300px|&lt;br /&gt;
Заголовок=LinuxFormat Вердикт|&lt;br /&gt;
Содержание=&lt;br /&gt;
'''Opera 9'''&lt;br /&gt;
&lt;br /&gt;
Developer: Opera Software&lt;br /&gt;
&lt;br /&gt;
Web: http://www.opera.com&lt;br /&gt;
&lt;br /&gt;
Price: Бесплатно по закрытой лицензии&lt;br /&gt;
&lt;br /&gt;
*Функциональность 9/10&lt;br /&gt;
*Производительность 9/10&lt;br /&gt;
*Простота использования 9/10&lt;br /&gt;
*Документация 7/10&lt;br /&gt;
&lt;br /&gt;
Хорош и для продвинутых пользователей, и для простых любителей&lt;br /&gt;
Интернета, но возможны проблемы с сайтами, использующими Ajax.&lt;br /&gt;
&lt;br /&gt;
'''Рейтинг 8/10'''&lt;br /&gt;
}}&lt;/div&gt;</summary>
		<author><name>Skryabin yuri</name></author>	</entry>

	<entry>
		<id>http://wiki.linuxformat.ru/wiki/LXF84:AC3D_6</id>
		<title>LXF84:AC3D 6</title>
		<link rel="alternate" type="text/html" href="http://wiki.linuxformat.ru/wiki/LXF84:AC3D_6"/>
				<updated>2008-04-04T06:15:32Z</updated>
		
		<summary type="html">&lt;p&gt;Skryabin yuri: Врезки и вердикт&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==AC3D 6==&lt;br /&gt;
''Linux не обижен инструментами 3D-моделирования, но почти все они – не для обычного&lt;br /&gt;
пользователя. '''Ник Вейч''' отыскал среди них не требующий семи пядей во лбу.''&lt;br /&gt;
&lt;br /&gt;
{{врезка|Ширина=200px|left|&lt;br /&gt;
Заголовок=Вкратце...|&lt;br /&gt;
Содержание=Платный инструмент объемного моделирования со славной историей. Аналоги - Blender, Maya и Realsoft 3D.}}&lt;br /&gt;
[[Image:Img_84_00_0.png|thumb|300px|От простейших предметов до сложных игровых миров – AC3D умеет делать все.]]&lt;br /&gt;
Производители спецэффектов давно влюблены в платформу Linux – она экономит время и деньги в сравнении с другими, менее стабильными, системами. Но их фирменные приложения вряд ли доступны для эффективного использования непрофессионалами. Поприветствуем же AC3D, программу, достаточно простую для домашнего пользователя и, при этом, достаточно мощную по всем параметрам. Ныне она празднует свое десятилетие (первоначально AC3D создавалась для Unix и Windows), причем все это время она активно развивалась.&lt;br /&gt;
===Всеобщая совместимость===&lt;br /&gt;
AC3D гораздо лучше других Linux-инструментов справляется с открытием файлов 3D Studio Max, LightWave 3D, DXF (AutoCAD) и...&lt;br /&gt;
всех остальных. Огромное количество сред разработки, в которых теперь создаются 3D-объекты, а также проприетарная природа систем рендеринга привели к появлению множества разных форматов. Способность AC3D понимать их – одно из тех качеств программы, которые окупают расходы; вот только иногда в процессе трансляции теряются некоторые текстуры и объекты.&lt;br /&gt;
&lt;br /&gt;
Благодаря кросс-платформенности AC3D можно работать даже с теми форматами, которые на Linux обычно не поддерживаются – например, MilkShape (эта программа часто используется для моделирования арены компьютерных игр). Возможность экспорта в эти форматы существенна, если необходимо включить в рабочий процесс другие закрытые программы. Фактически, AC3D может запросто обращаться ко многим рендерерам (по умолчанию – POV-Ray), хотя это более полезно для Windows/Mac версии.&lt;br /&gt;
&lt;br /&gt;
===Интерфейс похорошел===&lt;br /&gt;
{{врезка|Ширина=200px|left|&lt;br /&gt;
Заголовок=Свойства навскидку|&lt;br /&gt;
Содержание=&lt;br /&gt;
*Ревизия интерфейса&lt;br /&gt;
[[Image:Img_84_00_0.png|thumb|В переработанном интерфейсе инструменты проще в использовании, да и на вид они проще!]]&lt;br /&gt;
*Подповерхности&lt;br /&gt;
[[Image:Img_84_00_0.png|thumb|С помощью «подповерхностей» значительно проще создавать «живые» фигуры.]]&lt;br /&gt;
}}&lt;br /&gt;
В версии 6 капитально обновился пользовательский интерфейс, основные инструменты получили цветные значки, теперь их нетрудно отыскать. По ощущению, программа стала значительно быстрее и отзывчивее, чем в предыдущей версии. Возможно, это просто следствие обновления наших компьютеров с тех пор, как мы в последний раз рассматривали AC3D – OpenGL-рендеринг видов тоже заметно порезвел.&lt;br /&gt;
&lt;br /&gt;
Наряду с косметикой, перемены есть и в функциональности. Наиболее заметная из них – оконная иерархия объектов, с помощью которой можно включить/отключить видимость различных объектов или просто убедиться, что редактируется нужная фигура. Новые органы&lt;br /&gt;
управления ограниченным движением, а также улучшенная видимость границ полей редактирования упрощают редактирование фигур,&lt;br /&gt;
а изменения в процессе выбора означают, что вам больше не понадобится клавиатурная гимнастика для отметки нужных вершин.&lt;br /&gt;
&lt;br /&gt;
AC3D довольно долго считалась инструментом доводки, ведь в ней отсутствовали многие сложные функции, доступные в других&lt;br /&gt;
платных программах. Это во многом справедливо: AC3D в основном полигональный/вершинный редактор без прихотливых режимов&lt;br /&gt;
моделирования; но теперь он поддерживает впечатляющую функцию работы с «подповерхностями» (соподчиненными поверхностями), которая существенно упрощает создание «органичных» фигур и плавных изгибов. Если у вас уже есть Maya, то вы, возможно, не захотите связываться с AC3D (при всем многообразии поддерживаемых форматов). Если же вы устали бороться с превосходным, но сложным Blender – загрузите (свободно) пробную версию AC3D, и попробуйте начать с нее.&lt;br /&gt;
{{врезка|Ширина=300px|&lt;br /&gt;
Заголовок=LinuxFormat Вердикт|&lt;br /&gt;
Содержание=&lt;br /&gt;
'''AC3D 6'''&lt;br /&gt;
&lt;br /&gt;
Разработчик: Inivis&lt;br /&gt;
&lt;br /&gt;
Сайт: http://www.ac3d.org&lt;br /&gt;
&lt;br /&gt;
Цена: $69.95&lt;br /&gt;
&lt;br /&gt;
*Функциональность 9/10&lt;br /&gt;
*Производительность 9/10&lt;br /&gt;
*Простота использования 8/10&lt;br /&gt;
*Цена 8/10&lt;br /&gt;
&lt;br /&gt;
$69,95 – сущая безделица за такой&lt;br /&gt;
основательный, такой простой и такой&lt;br /&gt;
полезный товар.&lt;br /&gt;
&lt;br /&gt;
'''Рейтинг 9/10'''&lt;br /&gt;
}}&lt;/div&gt;</summary>
		<author><name>Skryabin yuri</name></author>	</entry>

	<entry>
		<id>http://wiki.linuxformat.ru/wiki/%D0%A4%D0%B0%D0%B9%D0%BB:Img_84_00_0.png</id>
		<title>Файл:Img 84 00 0.png</title>
		<link rel="alternate" type="text/html" href="http://wiki.linuxformat.ru/wiki/%D0%A4%D0%B0%D0%B9%D0%BB:Img_84_00_0.png"/>
				<updated>2008-04-04T05:57:55Z</updated>
		
		<summary type="html">&lt;p&gt;Skryabin yuri: Врем. рис.&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Врем. рис.&lt;/div&gt;</summary>
		<author><name>Skryabin yuri</name></author>	</entry>

	<entry>
		<id>http://wiki.linuxformat.ru/wiki/LXF84:AC3D_6</id>
		<title>LXF84:AC3D 6</title>
		<link rel="alternate" type="text/html" href="http://wiki.linuxformat.ru/wiki/LXF84:AC3D_6"/>
				<updated>2008-04-04T05:50:29Z</updated>
		
		<summary type="html">&lt;p&gt;Skryabin yuri: Текст&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==AC3D 6==&lt;br /&gt;
''Linux не обижен инструментами 3D-моделирования, но почти все они – не для обычного&lt;br /&gt;
пользователя. '''Ник Вейч''' отыскал среди них не требующий семи пядей во лбу.''&lt;br /&gt;
&lt;br /&gt;
Производители спецэффектов давно влюблены в платформу Linux – она экономит время и деньги в сравнении с другими, менее стабильными, системами. Но их фирменные приложения вряд ли доступны для эффективного использования непрофессионалами. Поприветствуем же AC3D, программу, достаточно простую для домашнего пользователя и, при этом, достаточно мощную по всем параметрам. Ныне она празднует свое десятилетие (первоначально AC3D создавалась для Unix и Windows), причем все это время она активно развивалась.&lt;br /&gt;
===Всеобщая совместимость===&lt;br /&gt;
AC3D гораздо лучше других Linux-инструментов справляется с открытием файлов 3D Studio Max, LightWave 3D, DXF (AutoCAD) и...&lt;br /&gt;
всех остальных. Огромное количество сред разработки, в которых теперь создаются 3D-объекты, а также проприетарная природа систем рендеринга привели к появлению множества разных форматов. Способность AC3D понимать их – одно из тех качеств программы, которые окупают расходы; вот только иногда в процессе трансляции теряются некоторые текстуры и объекты.&lt;br /&gt;
&lt;br /&gt;
Благодаря кросс-платформенности AC3D можно работать даже с теми форматами, которые на Linux обычно не поддерживаются – например, MilkShape (эта программа часто используется для моделирования арены компьютерных игр). Возможность экспорта в эти форматы существенна, если необходимо включить в рабочий процесс другие закрытые программы. Фактически, AC3D может запросто обращаться ко многим рендерерам (по умолчанию – POV-Ray), хотя это более полезно для Windows/Mac версии.&lt;br /&gt;
&lt;br /&gt;
===Интерфейс похорошел===&lt;br /&gt;
В версии 6 капитально обновился пользовательский интерфейс, основные инструменты получили цветные значки, теперь их нетрудно отыскать. По ощущению, программа стала значительно быстрее и отзывчивее, чем в предыдущей версии. Возможно, это просто следствие обновления наших компьютеров с тех пор, как мы в последний раз рассматривали AC3D – OpenGL-рендеринг видов тоже заметно порезвел.&lt;br /&gt;
&lt;br /&gt;
Наряду с косметикой, перемены есть и в функциональности. Наиболее заметная из них – оконная иерархия объектов, с помощью которой можно включить/отключить видимость различных объектов или просто убедиться, что редактируется нужная фигура. Новые органы&lt;br /&gt;
управления ограниченным движением, а также улучшенная видимость границ полей редактирования упрощают редактирование фигур,&lt;br /&gt;
а изменения в процессе выбора означают, что вам больше не понадобится клавиатурная гимнастика для отметки нужных вершин.&lt;br /&gt;
&lt;br /&gt;
AC3D довольно долго считалась инструментом доводки, ведь в ней отсутствовали многие сложные функции, доступные в других&lt;br /&gt;
платных программах. Это во многом справедливо: AC3D в основном полигональный/вершинный редактор без прихотливых режимов&lt;br /&gt;
моделирования; но теперь он поддерживает впечатляющую функцию работы с «подповерхностями» (соподчиненными поверхностями), которая существенно упрощает создание «органичных» фигур и плавных изгибов. Если у вас уже есть Maya, то вы, возможно, не захотите связываться с AC3D (при всем многообразии поддерживаемых форматов). Если же вы устали бороться с превосходным, но сложным Blender – загрузите (свободно) пробную версию AC3D, и попробуйте начать с нее.&lt;/div&gt;</summary>
		<author><name>Skryabin yuri</name></author>	</entry>

	<entry>
		<id>http://wiki.linuxformat.ru/wiki/LXF84:Google_Earth</id>
		<title>LXF84:Google Earth</title>
		<link rel="alternate" type="text/html" href="http://wiki.linuxformat.ru/wiki/LXF84:Google_Earth"/>
				<updated>2008-04-04T04:36:04Z</updated>
		
		<summary type="html">&lt;p&gt;Skryabin yuri: доб Вердикт LXF&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Google Earth ==&lt;br /&gt;
''Предвидя захват Земли хакерами, '''Грэм Моррисон''' рассматривает проект Google – никогда ещё виртуальная жизнь не была так хороша.''&lt;br /&gt;
&lt;br /&gt;
{{врезка|Ширина=200px|left|&lt;br /&gt;
Заголовок=Вкратце...|&lt;br /&gt;
Содержание=Исследуйте Землю за своим рабочим столом с помощью спутниковых изображений и 3D-данных. См. также: Celestia или ожидаемый NASA World Wind 1.5.}}&lt;br /&gt;
[[Image:Img_84_08_1.png|thumb|300px|Пусть Большой Каньон находится на другой стороне планеты – исследовать фотогеничную американскую бездну можно, не выходя из-за компьютера.]]&lt;br /&gt;
Надо признать, что год назад, когда был выпущен Google Earth для Windows, впечатление было сильным. Мы завистливо наблюдали, как знакомые почитатели Windows и Mac запускают виртуальную планету Google и бороздят Тихий океан в поисках неисследованных территорий&lt;br /&gt;
или просто удобного места для отпуска. Но больше мы им не завидуем! Google cовершил благородный поступок и выпустил родной&lt;br /&gt;
порт для старого доброго Linux. Родной – это вам не полуподпольные библиотеки Wine для обработки системных вызовов Windows, как в&lt;br /&gt;
Picasa (см. обзор [[LXF83|LXF83]]). Всё сделано основательно, с помощью Qt и под OpenGL.&lt;br /&gt;
&lt;br /&gt;
Для тех, кому пока не посчастливилось наблюдать Google Earth в действии – это естественное расширение Google Maps. При первом запуске мы видим голубое пятнышко Земли с расстояния порядка 15 000 миль. Прокрутка мыши приближает нас к родной планете, пока мы не зависнем над США. Чем дольше вы держитесь на одном месте, тем детальнее становится вид – Google Earth безостановочно транслирует спутниковое изображение со своего сервера. Именно поэтому вам понадобится как минимум широкополосное подключение к Интернету: только тогда вы&lt;br /&gt;
насладитесь в полной мере.&lt;br /&gt;
&lt;br /&gt;
Уровень детализации зависит от местонахождения. США, например, могут похвастать наилучшим покрытием: здесь не диво разглядеть автомобиль или даже людей. Детализация других частей света различна, чаще всего она доходит примерно до 15 метров на пиксель.&lt;br /&gt;
&lt;br /&gt;
=== Полёт навигатора ===&lt;br /&gt;
{{врезка|Ширина=200px|left|&lt;br /&gt;
Заголовок=Свойства навскидку|&lt;br /&gt;
Содержание=&lt;br /&gt;
*Высота гор&lt;br /&gt;
[[Image:Img_84_08_2.png|thumb|Использование высотных данных означает, что горы типа Эвереста поднимаются над&lt;br /&gt;
земной поверхностью.]]&lt;br /&gt;
*Отображение зданий&lt;br /&gt;
[[Image:Img_84_08_3.png|thumb|В нескольких городах США отображаются даже дома, а пользователи добавили&lt;br /&gt;
текстурные здания и в другие места.]]&lt;br /&gt;
}}&lt;br /&gt;
Секстант не понадобится: навигация сводится к набору на клавиатуре названия места, куда вы хотели бы попасть. Вид плавно удаляется в космос, затем перемещается к месту назначения. Приоритеты расставлены с американских позиций – например, если набрать&lt;br /&gt;
«Birmingham», то вы угодите в Алабаму, а не в более крупный город в Британии.&lt;br /&gt;
&lt;br /&gt;
Прибыв на место назначения, можно щёлкать и перемещать карту мышью (совсем как в Google Maps). Но если нажать и удерживать&lt;br /&gt;
среднюю кнопку мыши, вы измените угол зрения со стандартного (сверху вниз, как со спутника) до совершенно горизонтального,&lt;br /&gt;
если захотите. Google Maps так не умеет – а что особенно поражает, Google Earth использует высотные данные для приближённого&lt;br /&gt;
отображения неровностей земной поверхности. Например, посетив Эверест или Большой Каньон, вы увидите их реалистичные модели.&lt;br /&gt;
&lt;br /&gt;
Надоело выискивать собственное местонахождение? Интернет полон открытиями других людей. Они пользуются KML, Keyhole Markup Language, и отмечают интересные места, новые 3D-модели (с текстурами!), фото, клипы и информацию, напрямую связанные с Интернетом. Поиски могут вывести и на рекламодателей Google, аналогично страницам поиска в поисковой машине. Это может пригодиться, если вы, скажем, ищете ближайший ресторан в Непале, а программа в этом помочь не может. Закладки делаются на всех интересных местах, совершенно так же, как в обычном браузере.&lt;br /&gt;
&lt;br /&gt;
Захлопает бабочка крылышками на другой стороне планеты – и Google Earth создаст у вас иллюзию, что двойным щелчком мыши можно&lt;br /&gt;
вмешаться в это событие и наблюдать наступивший хаос. Google Earth будит желание поохотиться за метеоритными кратерами или найти исток Амазонки. Бесплатный ресурс такой мощи просто не за что критиковать.&lt;br /&gt;
{{врезка|Ширина=300px|&lt;br /&gt;
Заголовок=LinuxFormat Вердикт|&lt;br /&gt;
Содержание=&lt;br /&gt;
'''Google Earth'''&lt;br /&gt;
&lt;br /&gt;
Разработчик: Google&lt;br /&gt;
&lt;br /&gt;
Сайт: http://earth.google.com&lt;br /&gt;
&lt;br /&gt;
Цена: Бесплатно по закрытой лицензии&lt;br /&gt;
&lt;br /&gt;
*Функциональность 10/10&lt;br /&gt;
*Производительность 9/10&lt;br /&gt;
*Простота использования 9/10&lt;br /&gt;
*Документация 9/10&lt;br /&gt;
&lt;br /&gt;
Если весь мир – сцена, то Google Earth – театр. Простая в использовании, захватывающая и ободряюще практичная программа.&lt;br /&gt;
&lt;br /&gt;
'''Рейтинг 9/10'''&lt;br /&gt;
}}&lt;/div&gt;</summary>
		<author><name>Skryabin yuri</name></author>	</entry>

	<entry>
		<id>http://wiki.linuxformat.ru/wiki/LXF84:Google_Earth</id>
		<title>LXF84:Google Earth</title>
		<link rel="alternate" type="text/html" href="http://wiki.linuxformat.ru/wiki/LXF84:Google_Earth"/>
				<updated>2008-03-25T10:36:05Z</updated>
		
		<summary type="html">&lt;p&gt;Skryabin yuri: Врезка&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Google Earth ==&lt;br /&gt;
''Предвидя захват Земли хакерами, '''Грэм Моррисон''' рассматривает проект Google – никогда ещё виртуальная жизнь не была так хороша.''&lt;br /&gt;
&lt;br /&gt;
{{врезка|Ширина=200px|left|&lt;br /&gt;
Заголовок=Вкратце...|&lt;br /&gt;
Содержание=Исследуйте Землю за своим рабочим столом с помощью спутниковых изображений и 3D-данных. См. также: Celestia или ожидаемый NASA World Wind 1.5.}}&lt;br /&gt;
[[Image:Img_84_08_1.png|thumb|300px|Пусть Большой Каньон находится на другой стороне планеты – исследовать фотогеничную американскую бездну можно, не выходя из-за компьютера.]]&lt;br /&gt;
Надо признать, что год назад, когда был выпущен Google Earth для Windows, впечатление было сильным. Мы завистливо наблюдали, как знакомые почитатели Windows и Mac запускают виртуальную планету Google и бороздят Тихий океан в поисках неисследованных территорий&lt;br /&gt;
или просто удобного места для отпуска. Но больше мы им не завидуем! Google cовершил благородный поступок и выпустил родной&lt;br /&gt;
порт для старого доброго Linux. Родной – это вам не полуподпольные библиотеки Wine для обработки системных вызовов Windows, как в&lt;br /&gt;
Picasa (см. обзор [[LXF83|LXF83]]). Всё сделано основательно, с помощью Qt и под OpenGL.&lt;br /&gt;
&lt;br /&gt;
Для тех, кому пока не посчастливилось наблюдать Google Earth в действии – это естественное расширение Google Maps. При первом запуске мы видим голубое пятнышко Земли с расстояния порядка 15 000 миль. Прокрутка мыши приближает нас к родной планете, пока мы не зависнем над США. Чем дольше вы держитесь на одном месте, тем детальнее становится вид – Google Earth безостановочно транслирует спутниковое изображение со своего сервера. Именно поэтому вам понадобится как минимум широкополосное подключение к Интернету: только тогда вы&lt;br /&gt;
насладитесь в полной мере.&lt;br /&gt;
&lt;br /&gt;
Уровень детализации зависит от местонахождения. США, например, могут похвастать наилучшим покрытием: здесь не диво разглядеть автомобиль или даже людей. Детализация других частей света различна, чаще всего она доходит примерно до 15 метров на пиксель.&lt;br /&gt;
&lt;br /&gt;
=== Полёт навигатора ===&lt;br /&gt;
{{врезка|Ширина=200px|left|&lt;br /&gt;
Заголовок=Свойства навскидку|&lt;br /&gt;
Содержание=&lt;br /&gt;
*Высота гор&lt;br /&gt;
[[Image:Img_84_08_2.png|thumb|Использование высотных данных означает, что горы типа Эвереста поднимаются над&lt;br /&gt;
земной поверхностью.]]&lt;br /&gt;
*Отображение зданий&lt;br /&gt;
[[Image:Img_84_08_3.png|thumb|В нескольких городах США отображаются даже дома, а пользователи добавили&lt;br /&gt;
текстурные здания и в другие места.]]&lt;br /&gt;
}}&lt;br /&gt;
Секстант не понадобится: навигация сводится к набору на клавиатуре названия места, куда вы хотели бы попасть. Вид плавно удаляется в космос, затем перемещается к месту назначения. Приоритеты расставлены с американских позиций – например, если набрать&lt;br /&gt;
«Birmingham», то вы угодите в Алабаму, а не в более крупный город в Британии.&lt;br /&gt;
&lt;br /&gt;
Прибыв на место назначения, можно щёлкать и перемещать карту мышью (совсем как в Google Maps). Но если нажать и удерживать&lt;br /&gt;
среднюю кнопку мыши, вы измените угол зрения со стандартного (сверху вниз, как со спутника) до совершенно горизонтального,&lt;br /&gt;
если захотите. Google Maps так не умеет – а что особенно поражает, Google Earth использует высотные данные для приближённого&lt;br /&gt;
отображения неровностей земной поверхности. Например, посетив Эверест или Большой Каньон, вы увидите их реалистичные модели.&lt;br /&gt;
&lt;br /&gt;
Надоело выискивать собственное местонахождение? Интернет полон открытиями других людей. Они пользуются KML, Keyhole Markup Language, и отмечают интересные места, новые 3D-модели (с текстурами!), фото, клипы и информацию, напрямую связанные с Интернетом. Поиски могут вывести и на рекламодателей Google, аналогично страницам поиска в поисковой машине. Это может пригодиться, если вы, скажем, ищете ближайший ресторан в Непале, а программа в этом помочь не может. Закладки делаются на всех интересных местах, совершенно так же, как в обычном браузере.&lt;br /&gt;
&lt;br /&gt;
Захлопает бабочка крылышками на другой стороне планеты – и Google Earth создаст у вас иллюзию, что двойным щелчком мыши можно&lt;br /&gt;
вмешаться в это событие и наблюдать наступивший хаос. Google Earth будит желание поохотиться за метеоритными кратерами или найти исток Амазонки. Бесплатный ресурс такой мощи просто не за что критиковать.&lt;/div&gt;</summary>
		<author><name>Skryabin yuri</name></author>	</entry>

	<entry>
		<id>http://wiki.linuxformat.ru/wiki/LXF86:Java</id>
		<title>LXF86:Java</title>
		<link rel="alternate" type="text/html" href="http://wiki.linuxformat.ru/wiki/LXF86:Java"/>
				<updated>2008-03-20T05:35:06Z</updated>
		
		<summary type="html">&lt;p&gt;Skryabin yuri: Изменена ссылка на следующую статью&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Цикл/Java}}&lt;br /&gt;
&lt;br /&gt;
=== Хранение данных ===&lt;br /&gt;
''ЧАСТЬ 3: Даже самой замечательной программе надо откуда-то черпать данные для своей работы. Данные, как известно, хранятся в файлах. Тему продолжает '''Антон Черноусов'''.''&lt;br /&gt;
&lt;br /&gt;
В предыдущей статье из цикла, посвященного программированию на Java, были рассмотрены вопросы организации простых вычислений, ветвлений, циклов, а также генерации и обработки исключений.&lt;br /&gt;
&lt;br /&gt;
В течение третьего урока мы поговорим о работе с файлами, о протоколировании работы программы и коснемся методов работы с&lt;br /&gt;
XML-данными.&lt;br /&gt;
&lt;br /&gt;
=== Файлы — потоки ===&lt;br /&gt;
Сказочное королевство под руководством царевны Несмеяны (так как cупруг практически всегда отсутствовал), благодаря талантам и приобретенным навыкам, стало разрастаться, и результаты полюдья просто-напросто перестали помещаться в семейный чулан. Чтобы накапливать и хранить богатства, потребовались дополнительные помещения, роль которых для нас привычно играют файлы.&lt;br /&gt;
&lt;br /&gt;
Отношение к файлам в Java достаточно непростое: если рассматривать файл как устройство для ввода/вывода информации — с этой точ&lt;br /&gt;
ки зрения он подобен блоку памяти или экрану, интерфейс доступа к которому унифицирован: это поток. Но несмотря на унифицированный интерфейс, существует большое количество классов сходной функциональности, в которых легко запутаться.&lt;br /&gt;
&lt;br /&gt;
Поток можно представить в виде ленточного конвейера с последовательным размещением или извлечением данных, при использовании&lt;br /&gt;
которого задача программиста сводиться к осуществлению операций «поместить/читать» данные, а остальные детали реализации скрыты&lt;br /&gt;
от него.&lt;br /&gt;
&lt;br /&gt;
=== Чтение данных ===&lt;br /&gt;
Разнообразие классов для работы с файлами позволяет выбрать для себя ту связку, которая больше нравится. Лично я для чтения данных использую BufferedReader, InputStreamReader и FileInputStream. Собственно взаимодействие этих классов для программиста заканчивается в момент создания экземпляра BufferedReader, что делается следующим образом:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang = &amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
BufferedReader br = null;&lt;br /&gt;
br = new BufferedReader(new InputStreamReader(new FileInputStream(pathToFile), encoding));&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
В процессе создания участвуют строковые переменные, содержащие путь к файлу и кодировку, в которой производится считывание&lt;br /&gt;
данных: pathToFile и encoding. В классах, работающих с файлами, считается обязательным создавать переменную для кодировки по умолчанию:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang = &amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
protected static String DEFAULT_ENCODING = &amp;quot;UTF-8&amp;quot;;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Любой текстовый файл можно представить себе в виде набора строк, поэтому давайте реализуем метод для считывания содержимого&lt;br /&gt;
файла в массив String[]. Далее представлен метод rippedCurrentFile(path ToFile, encoding) класса FileRipper, который извлекает данные из файла с помощью метода readLine() экземпляра класса BufferedReader:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang = &amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
protected boolean rippedCurrentFile(String pathToFile, String encoding) {&lt;br /&gt;
  // connecting to file&lt;br /&gt;
  BufferedReader br = null;&lt;br /&gt;
  try {&lt;br /&gt;
    br = new BufferedReader(new InputStreamReader(new FileInputStream(pathToFile),encoding));&lt;br /&gt;
  } &lt;br /&gt;
  catch (UnsupportedEncodingException e) {&lt;br /&gt;
    this.error = FILE_ERROR_UNSUPPORTED_ENCODING; return false;&lt;br /&gt;
  } &lt;br /&gt;
  catch (FileNotFoundException e) {&lt;br /&gt;
    this.error = FILE_ERROR_NO_FILE; return false;&lt;br /&gt;
  }&lt;br /&gt;
  // ripping the file&lt;br /&gt;
  String str = null;&lt;br /&gt;
  ArrayList allStrings = new ArrayList();&lt;br /&gt;
  try {&lt;br /&gt;
    while (!(str = br.readLine()).equals(null)) { allStrings.add(str); }&lt;br /&gt;
  } &lt;br /&gt;
  catch (IOException e) {&lt;br /&gt;
    this.error = FILE_ERROR_IO_READ; return false;&lt;br /&gt;
  } &lt;br /&gt;
  catch (NullPointerException e) {&lt;br /&gt;
    this.error = FILE_ERROR_END_OF_FILE;&lt;br /&gt;
  }&lt;br /&gt;
  // free the resources&lt;br /&gt;
  try {&lt;br /&gt;
    br.close();&lt;br /&gt;
  } &lt;br /&gt;
  catch (IOException e) {&lt;br /&gt;
    this.error = FILE_ERROR_IO_CLOSE; return false;&lt;br /&gt;
  }&lt;br /&gt;
  this.allStrings = (String[]) allStrings.toArray(new String[0]); &lt;br /&gt;
  return true;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Полный код примера, в том числе код класса ConsoleToFileRipper, применяющий экземпляр класса FileRipper для извлечения данных из файла, можно найти на диске в каталоге '''examples 1'''.&lt;br /&gt;
&lt;br /&gt;
=== Запись данных ===&lt;br /&gt;
Процесс записи данных в файл хоть и отличается от чтения, но тоже достаточно похож на организацию конвейера. Для записи&lt;br /&gt;
я обычно использую связку BufferedWriter, OutputStreamWriter, FileOutputStream.&lt;br /&gt;
&amp;lt;source lang = &amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
BufferedWriter out;&lt;br /&gt;
out = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(pathToFile), encoding));&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Для освобождения ресурсов, которые используют экземпляры классов BufferedReader и BufferedWriter, необходимо вызвать метод&lt;br /&gt;
close().&lt;br /&gt;
&lt;br /&gt;
Далее приведу простой пример метода, который записывает строковый массив в файл (полный код метода расположен на диске в&lt;br /&gt;
директории '''examples 2'''):&lt;br /&gt;
&amp;lt;source lang = &amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
public boolean createCurrentFile(String pathToFile, String[] allStrings, String encoding){&lt;br /&gt;
  try {&lt;br /&gt;
    BufferedWriter out;&lt;br /&gt;
    out = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(pathToFile), encoding));&lt;br /&gt;
    for (int i = 0; i &amp;lt; allStrings.length; i++) {&lt;br /&gt;
      out.write(allStrings[i]); out.write(‘\n’);&lt;br /&gt;
    }&lt;br /&gt;
    out.close();&lt;br /&gt;
  } &lt;br /&gt;
  catch (IOException e) {&lt;br /&gt;
    e.printStackTrace(); &lt;br /&gt;
    return false;&lt;br /&gt;
  }&lt;br /&gt;
  return true;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Свободный доступ ===&lt;br /&gt;
В представленных ранее примерах доступ к данным осуществляется последовательно, что не всегда удобно (хотя в большинстве случаев именно такой доступ и используется). Для осуществления чтения и записи данных из файла в произвольном порядке существует специальный класс RandomAccessFile, экземпляр которого создается следующим образом:&lt;br /&gt;
&amp;lt;source lang = &amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
RandomAccessFile raf = new RandomAccessFile(pathToFile, mode);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
При этом pathToFile — путь до файла, а mode — режим работы. mode может принимать значения: r (только чтение), rw (чтение-запись), rws (чтение-запись с синхронным сохранением содержимого и метаданных), rwd (чтение-запись с синхронным сохранением содержимого файла). К сожалению, кодировку указать нельзя. Огромным преимуществом подхода является то, что с помощью метода getFilePointer() можно узнать текущее месторасположение указателя, а с помощью метода seek() можно передвинуть указатель в необходимое место в файле. Я предпочитаю не использовать данный класс — считайте это личным предубеждением.&lt;br /&gt;
&lt;br /&gt;
=== Протоколирование работы программы ===&lt;br /&gt;
Для контроля и анализа работы приложения существуют методы протоколирования. Популярным инструментом для этих целей в мире&lt;br /&gt;
Java является библиотека Log4j, которая разрабатывается в Apache Software Foundation. Текущую версию можно загрузить с [http://logging.apache.org/[http://logging.apache.org/]].&lt;br /&gt;
&lt;br /&gt;
Для использования библиотеки необходимо создать конфигурационный файл, который описывает, что, куда и как нужно протоколировать. Log4j имеет три базовые составляющие: logger, appender и layout.&lt;br /&gt;
&lt;br /&gt;
layout — это элементы, определяющие вид и содержание записей. Изначально имеется несколько заранее созданных layout-ов, а в случае необходимости можно создать свой собственный.&lt;br /&gt;
&lt;br /&gt;
Appender — это элемент, определяющий местоположение протокола, с его помощью задается тип протоколирования:&lt;br /&gt;
* файловое протоколирование (FileAppender);&lt;br /&gt;
* консольное протоколирование (ConsoleAppender);&lt;br /&gt;
* протоколирование в базы данных (JDBCAppender);&lt;br /&gt;
* протоколирование на SMTP-сервера (SMTPAppender) и др.&lt;br /&gt;
&lt;br /&gt;
Logger — это элемент, который обеспечивает протоколирование какого-либо события. Если обратиться к ранее приведенной аналогии&lt;br /&gt;
ленточного конвейера, logger — это и есть тот самый конвейер, вызывая методы которого, мы формируем протокол работы программы.&lt;br /&gt;
Элемент logger предусматривает следующие уровни протоколирования: DEBUG, INFO, WARN, ERROR, FATAL; уровням соответствуют методы класса org.apache.log4j.Logger: debug; info; warn; error; fatal.&lt;br /&gt;
&lt;br /&gt;
Ниже представлен пример записей для конфигурационного файла нашего приложения, которые нужно сохранить в файл с названием '''log.properties''' (название файла может быть любым).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 log4j.logger.simple=DEBUG, nameLogAppender&lt;br /&gt;
 log4j.appender.nameLogAppender=org.apache.log4j.FileAppender&lt;br /&gt;
 log4j.appender.nameLogAppender.File=nameLogFile.log&lt;br /&gt;
 log4j.appender.nameLogAppender.layout=org.apache.log4j.SimpleLayout&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Первая строка указывает используемый уровень logger (DEBUG) и appender (nameLogAppender). Далее идут настройки appender: указание типа — FileAppender. В третьей строке указываем путь до файла журнала, а в последней — формат записи. Использовать экземпляр класса Logger можно примерно так (пример протоколирования приведен на диске в каталоге '''examples 3'''):&lt;br /&gt;
&amp;lt;source lang = &amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
File propertiesFile = new File(&amp;quot;log.properties&amp;quot;);&lt;br /&gt;
PropertyConfigurator.configure(propertiesFile.toString());&lt;br /&gt;
Logger logger = Logger.getLogger(&amp;quot;simple&amp;quot;);&lt;br /&gt;
logger.info(&amp;quot;the program has started&amp;quot;);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Документы XML ===&lt;br /&gt;
Проектируя и создавая ПО, невозможно не столкнутся с миром XML (Extensible Markup Language). XML был создан в недрах World Wide&lt;br /&gt;
Web Consortium (W3C) для преодоления ограничений языка HTML. Можно сказать, что HTML — один из самых успешных языков, область&lt;br /&gt;
его использования с каждым годом растет (в основном в объемах). Несмотря на это, почему же W3C создал XML, и зачем вам использовать этот язык? В чем ограниченность HTML? Ответ на эти вопросы один:XML был создан для обеспечения взаимодействия разнородных систем.&lt;br /&gt;
&lt;br /&gt;
HTML, как и любой другой текстовый язык, не позволяет перенести смысл тех данных, которые он хранит. XML был разработан для решения этой задачи с прицелом на Web, но получился таким удачным, что его стали использовать практически везде. Суть XML в том, что он хранит семантический смысл данных, поэтому выполнив анализ такого XML-документа, система может «понять» полученные данные. В Интернете существует большое количество информации, посвященной XML (например, [http://www.ibm.com/developerworks/xml/[www.ibm.com/developerworks/xml/]]), поэтому не будем подробно останавливаться на его преимуществах, а сразу приступим к использованию.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang = &amp;quot;xml&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;?xml version=&amp;quot;1.0&amp;quot; ?&amp;gt;&lt;br /&gt;
&amp;lt;line name=&amp;quot;firstLine&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;point id=&amp;quot;1&amp;quot; theX=&amp;quot;1&amp;quot; theY=&amp;quot;1&amp;quot;/&amp;gt;&lt;br /&gt;
&amp;lt;point id=&amp;quot;2&amp;quot; theX=&amp;quot;2&amp;quot; theY=&amp;quot;2&amp;quot;/&amp;gt;&lt;br /&gt;
&amp;lt;/line&amp;gt;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Выше приведен простой пример XML-документа, содержащего корневой элемент line, который, в свою очередь, содержит два узла с&lt;br /&gt;
тремя атрибутами (id, theX, theY) каждый.&lt;br /&gt;
&lt;br /&gt;
=== Создание XML-документа ===&lt;br /&gt;
Говоря про создание XML-документа, я подразумеваю создание дерева XML-документа в памяти системы, то есть объекта DOM (Document Object Model). DOM была создана W3C, и это — официальная Рекомендация консорциума. В противовес DOM существует SAX (Simple API for XML). С моделью SAX можно ознакомиться более подробно в&lt;br /&gt;
[http://www-128.ibm.com/developerworks/ru/views/xml/libraryview.jsp[http://www-128.ibm.com/developerworks/ru/views/xml/libraryview.jsp]]. Основная разница между методами заключается в том, что DOM обеспечивает виртуальное представление XML-файла в памяти системы, в то время как SAX — это событийная модель обработки, в которой в момент встречи определенного элемента вызывается соответствующее событие.&lt;br /&gt;
&lt;br /&gt;
Для создания «отображения» XML-файла в памяти системы необходимо воспользоваться классом Document, экземпляр которого можно получить следующим образом:&lt;br /&gt;
&amp;lt;source lang = &amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();&lt;br /&gt;
DocumentBuilder db = dbf.newDocumentBuilder();&lt;br /&gt;
Document doc = db.newDocument();&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Создание корневого узла XML документа можно выполняется так:&lt;br /&gt;
&amp;lt;source lang = &amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
Element root = doc.createElement(&amp;quot;line&amp;quot;);&lt;br /&gt;
root.setAttribute(&amp;quot;name&amp;quot;, &amp;quot;firstLine&amp;quot;);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
С помощью метода createElement(name) производится создание элементов, в то время как создание и установка значений атрибутов&lt;br /&gt;
элементов производится с помощью метода setAttribute(name, value), где name — имя атрибута, а value — его значение. С помощью метода appendChild можно добавить узел в элемент или произвести запись элемента в документ XML, например, так:&lt;br /&gt;
&amp;lt;source lang = &amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
root.appendChild(item);&lt;br /&gt;
doc.appendChild(root);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Более детально процесс создания XML документа на примере класса Line изложен в директории '''examples 4'''. При вызове метода&lt;br /&gt;
createDoc() этого класса создается экземпляр класса Document, идентичный приведенному ранее коду XML.&lt;br /&gt;
&lt;br /&gt;
=== Сохранение XML-документа ===&lt;br /&gt;
Для сохранения созданного в памяти документа предлагаю воспользоваться методом saveXML(docToSave, pathToFile, charSet). В процессе сохранения участвует уже знакомый нам OutputStreamWriter, а также экземпляр класса Transformer, который обеспечивает преобразование объекта DOMSource в выходной поток.&lt;br /&gt;
&amp;lt;source lang = &amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
public void saveXML(Document docToSave, String pathToFile, String charSet) {&lt;br /&gt;
  try {&lt;br /&gt;
    Writer target = new OutputStreamWriter(new FileOutputStream(pathToFile), charSet);&lt;br /&gt;
    Source source = new DOMSource(docToSave);&lt;br /&gt;
    StreamResult dest = new StreamResult(target);&lt;br /&gt;
    Transformer t = TransformerFactory.newInstance().newTransformer();&lt;br /&gt;
    t.setOutputProperty(OutputKeys.ENCODING, charSet);&lt;br /&gt;
    t.setOutputProperty(OutputKeys.INDENT, &amp;quot;yes&amp;quot;);&lt;br /&gt;
    t.transform(source, dest);  &lt;br /&gt;
    target.flush();&lt;br /&gt;
    target.close();&lt;br /&gt;
  } &lt;br /&gt;
  catch (Exception ex) {&lt;br /&gt;
    ex.printStackTrace();&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Реализация этого метода представлена на диске в директории '''examples 5'''.&lt;br /&gt;
&lt;br /&gt;
=== Загрузка XML-документа ===&lt;br /&gt;
Подобно сохранению XLM-документа, загрузка также достаточно просто выполняется с помощью экземпляра класса FileInputStream. Используя DocumentBuilderFactory, сгенерируем объект класса Document следующим образом:&lt;br /&gt;
&amp;lt;source lang = &amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
FileInputStream fis = new FileInputStream(pathToFile);&lt;br /&gt;
Document doc = DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(fis);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Фактически, создание документа происходит вследствие выполнения метода parse. Для детально рассмотрения процесса загрузки&lt;br /&gt;
XML документа обратитесь к директории '''examples 6''', расположенной на диске.&lt;br /&gt;
&lt;br /&gt;
=== Извлечение данных из XML-документа ===&lt;br /&gt;
Итак, что же делать с Document? Работать, естественно! Прежде чем приступить к обработке XML-документа, хочу обратить внимание на одну неприятную особенность: почти всегда XML документ содержит пустые узлы или символы перевода каретки (неизбежное зло форматирования). К сожалению, такая особенность существенно затрудняет процесс обработки XML-документа. Поэтому следует всегда проводить нормализацию с помощью определенного в интерфейсе метода normalize(), или, если реализация Document не имеет такой возможности или нормализация выполняется некорректно — воспользуйтесь методом normalizeDocument класса FileXMLReader (вы найдете его все в той же директории '''examples 6'''). Вызвать данный метод можно следующим образом:&lt;br /&gt;
&amp;lt;source lang = &amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
normalizeDocument(doc.getDocumentElement());&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Изложенный выше материал получился несколько другого формата, нежели предыдущие статьи. Статья содержит небольшие примеры&lt;br /&gt;
и отсылает на набор сознательно упрощенных готовых решений, благодаря которым вы сможете работать с файлами, производить прото-&lt;br /&gt;
колирование деятельности вашего приложения, начать работать с данными в формате XML. Цель приведенных примеров — обеспечить вас&lt;br /&gt;
необходимым минимумом информации и дать направление для поиска ответов на Ваши вопросы. В [[LXF87/88:Java|следующей статье]] мы расмотрим потоки.&lt;/div&gt;</summary>
		<author><name>Skryabin yuri</name></author>	</entry>

	<entry>
		<id>http://wiki.linuxformat.ru/wiki/LXF84:Google_Earth</id>
		<title>LXF84:Google Earth</title>
		<link rel="alternate" type="text/html" href="http://wiki.linuxformat.ru/wiki/LXF84:Google_Earth"/>
				<updated>2008-03-18T07:12:06Z</updated>
		
		<summary type="html">&lt;p&gt;Skryabin yuri: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Google Earth ==&lt;br /&gt;
''Предвидя захват Земли хакерами, '''Грэм Моррисон''' рассматривает проект Google – никогда ещё виртуальная жизнь не была так хороша.''&lt;br /&gt;
&lt;br /&gt;
{{врезка|Ширина=200px|left|&lt;br /&gt;
Заголовок=Вкратце...|&lt;br /&gt;
Содержание=Исследуйте Землю за своим рабочим столом с помощью спутниковых изображений и 3D-данных. См. также: Celestia или ожидаемый NASA World Wind 1.5.}}&lt;br /&gt;
[[Image:Img_84_08_1.png|thumb|300px|Пусть Большой Каньон находится на другой стороне планеты – исследовать фотогеничную американскую бездну можно, не выходя из-за компьютера.]]&lt;br /&gt;
Надо признать, что год назад, когда был выпущен Google Earth для Windows, впечатление было сильным. Мы завистливо наблюдали, как знакомые почитатели Windows и Mac запускают виртуальную планету Google и бороздят Тихий океан в поисках неисследованных территорий&lt;br /&gt;
или просто удобного места для отпуска. Но больше мы им не завидуем! Google cовершил благородный поступок и выпустил родной&lt;br /&gt;
порт для старого доброго Linux. Родной – это вам не полуподпольные библиотеки Wine для обработки системных вызовов Windows, как в&lt;br /&gt;
Picasa (см. обзор LXF83). Всё сделано основательно, с помощью Qt и под OpenGL.&lt;br /&gt;
&lt;br /&gt;
Для тех, кому пока не посчастливилось наблюдать Google Earth в действии – это естественное расширение Google Maps. При первом запуске мы видим голубое пятнышко Земли с расстояния порядка 15 000 миль. Прокрутка мыши приближает нас к родной планете, пока мы не зависнем над США. Чем дольше вы держитесь на одном месте, тем детальнее становится вид – Google Earth безостановочно транслирует спутниковое изображение со своего сервера. Именно поэтому вам понадобится как минимум широкополосное подключение к Интернету: только тогда вы&lt;br /&gt;
насладитесь в полной мере.&lt;br /&gt;
&lt;br /&gt;
Уровень детализации зависит от местонахождения. США, например, могут похвастать наилучшим покрытием: здесь не диво разглядеть автомобиль или даже людей. Детализация других частей света различна, чаще всего она доходит примерно до 15 метров на пиксель.&lt;br /&gt;
&lt;br /&gt;
=== Полёт навигатора ===&lt;br /&gt;
Секстант не понадобится: навигация сводится к набору на клавиатуре названия места, куда вы хотели бы попасть. Вид плавно удаляется в космос, затем перемещается к месту назначения. Приоритеты расставлены с американских позиций – например, если набрать&lt;br /&gt;
«Birmingham», то вы угодите в Алабаму, а не в более крупный город в Британии.&lt;br /&gt;
&lt;br /&gt;
Прибыв на место назначения, можно щёлкать и перемещать карту мышью (совсем как в Google Maps). Но если нажать и удерживать&lt;br /&gt;
среднюю кнопку мыши, вы измените угол зрения со стандартного (сверху вниз, как со спутника) до совершенно горизонтального,&lt;br /&gt;
если захотите. Google Maps так не умеет – а что особенно поражает, Google Earth использует высотные данные для приближённого&lt;br /&gt;
отображения неровностей земной поверхности. Например, посетив Эверест или Большой Каньон, вы увидите их реалистичные модели.&lt;br /&gt;
&lt;br /&gt;
Надоело выискивать собственное местонахождение? Интернет полон открытиями других людей. Они пользуются KML, Keyhole Markup Language, и отмечают интересные места, новые 3D-модели (с текстурами!), фото, клипы и информацию, напрямую связанные с Интернетом. Поиски могут вывести и на рекламодателей Google, аналогично страницам поиска в поисковой машине. Это может пригодиться, если вы, скажем, ищете ближайший ресторан в Непале, а программа в этом помочь не может. Закладки делаются на всех интересных местах, совершенно так же, как в обычном браузере.&lt;br /&gt;
&lt;br /&gt;
Захлопает бабочка крылышками на другой стороне планеты – и Google Earth создаст у вас иллюзию, что двойным щелчком мыши можно&lt;br /&gt;
вмешаться в это событие и наблюдать наступивший хаос. Google Earth будит желание поохотиться за метеоритными кратерами или найти исток Амазонки. Бесплатный ресурс такой мощи просто не за что критиковать.&lt;/div&gt;</summary>
		<author><name>Skryabin yuri</name></author>	</entry>

	<entry>
		<id>http://wiki.linuxformat.ru/wiki/%D0%A4%D0%B0%D0%B9%D0%BB:Img_84_08_3.png</id>
		<title>Файл:Img 84 08 3.png</title>
		<link rel="alternate" type="text/html" href="http://wiki.linuxformat.ru/wiki/%D0%A4%D0%B0%D0%B9%D0%BB:Img_84_08_3.png"/>
				<updated>2008-03-18T06:02:55Z</updated>
		
		<summary type="html">&lt;p&gt;Skryabin yuri: Google Earth рис 3&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Google Earth рис 3&lt;/div&gt;</summary>
		<author><name>Skryabin yuri</name></author>	</entry>

	<entry>
		<id>http://wiki.linuxformat.ru/wiki/%D0%A4%D0%B0%D0%B9%D0%BB:Img_84_08_2.png</id>
		<title>Файл:Img 84 08 2.png</title>
		<link rel="alternate" type="text/html" href="http://wiki.linuxformat.ru/wiki/%D0%A4%D0%B0%D0%B9%D0%BB:Img_84_08_2.png"/>
				<updated>2008-03-18T06:01:45Z</updated>
		
		<summary type="html">&lt;p&gt;Skryabin yuri: Google Earth рис 2&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Google Earth рис 2&lt;/div&gt;</summary>
		<author><name>Skryabin yuri</name></author>	</entry>

	<entry>
		<id>http://wiki.linuxformat.ru/wiki/%D0%A4%D0%B0%D0%B9%D0%BB:Img_84_08_1.png</id>
		<title>Файл:Img 84 08 1.png</title>
		<link rel="alternate" type="text/html" href="http://wiki.linuxformat.ru/wiki/%D0%A4%D0%B0%D0%B9%D0%BB:Img_84_08_1.png"/>
				<updated>2008-03-18T06:00:49Z</updated>
		
		<summary type="html">&lt;p&gt;Skryabin yuri: Google Earth рис 1&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Google Earth рис 1&lt;/div&gt;</summary>
		<author><name>Skryabin yuri</name></author>	</entry>

	<entry>
		<id>http://wiki.linuxformat.ru/wiki/LXF84:Google_Earth</id>
		<title>LXF84:Google Earth</title>
		<link rel="alternate" type="text/html" href="http://wiki.linuxformat.ru/wiki/LXF84:Google_Earth"/>
				<updated>2008-03-18T05:40:27Z</updated>
		
		<summary type="html">&lt;p&gt;Skryabin yuri: Предварительный вариант&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Google Earth ==&lt;br /&gt;
''Предвидя захват Земли хакерами, '''Грэм Моррисон''' рассматривает проект Google – никогда ещё виртуальная жизнь не была так хороша.''&lt;br /&gt;
&lt;br /&gt;
Надо признать, что год назад, когда был выпущен Google Earth для Windows, впечатление было сильным. Мы завистливо наблюдали, как знакомые почитатели Windows и Mac запускают виртуальную планету Google и бороздят Тихий океан в поисках неисследованных территорий&lt;br /&gt;
или просто удобного места для отпуска. Но больше мы им не завидуем! Google cовершил благородный поступок и выпустил родной&lt;br /&gt;
порт для старого доброго Linux. Родной – это вам не полуподпольные библиотеки Wine для обработки системных вызовов Windows, как в&lt;br /&gt;
Picasa (см. обзор LXF83). Всё сделано основательно, с помощью Qt и под OpenGL.&lt;br /&gt;
&lt;br /&gt;
Для тех, кому пока не посчастливилось наблюдать Google Earth в действии – это естественное расширение Google Maps. При первом запуске мы видим голубое пятнышко Земли с расстояния порядка 15 000 миль. Прокрутка мыши приближает нас к родной планете, пока мы не зависнем над США. Чем дольше вы держитесь на одном месте, тем детальнее становится вид – Google Earth безостановочно транслирует спутниковое изображение со своего сервера. Именно поэтому вам понадобится как минимум широкополосное подключение к Интернету: только тогда вы&lt;br /&gt;
насладитесь в полной мере.&lt;br /&gt;
&lt;br /&gt;
Уровень детализации зависит от местонахождения. США, например, могут похвастать наилучшим покрытием: здесь не диво разглядеть автомобиль или даже людей. Детализация других частей света различна, чаще всего она доходит примерно до 15 метров на пиксель.&lt;br /&gt;
&lt;br /&gt;
=== Полёт навигатора ===&lt;br /&gt;
&lt;br /&gt;
Секстант не понадобится: навигация сводится к набору на клавиатуре названия места, куда вы хотели бы попасть. Вид плавно удаляется в космос, затем перемещается к месту назначения. Приоритеты расставлены с американских позиций – например, если набрать&lt;br /&gt;
«Birmingham», то вы угодите в Алабаму, а не в более крупный город в Британии.&lt;br /&gt;
&lt;br /&gt;
Прибыв на место назначения, можно щёлкать и перемещать карту мышью (совсем как в Google Maps). Но если нажать и удерживать&lt;br /&gt;
среднюю кнопку мыши, вы измените угол зрения со стандартного (сверху вниз, как со спутника) до совершенно горизонтального,&lt;br /&gt;
если захотите. Google Maps так не умеет – а что особенно поражает, Google Earth использует высотные данные для приближённого&lt;br /&gt;
отображения неровностей земной поверхности. Например, посетив Эверест или Большой Каньон, вы увидите их реалистичные модели.&lt;br /&gt;
&lt;br /&gt;
Надоело выискивать собственное местонахождение? Интернет полон открытиями других людей. Они пользуются KML, Keyhole Markup Language, и отмечают интересные места, новые 3D-модели (с текстурами!), фото, клипы и информацию, напрямую связанные с Интернетом. Поиски могут вывести и на рекламодателей Google, аналогично страницам поиска в поисковой машине. Это может пригодиться, если вы, скажем, ищете ближайший ресторан в Непале, а программа в этом помочь не может. Закладки делаются на всех интересных местах, совершенно так же, как в обычном браузере.&lt;br /&gt;
&lt;br /&gt;
Захлопает бабочка крылышками на другой стороне планеты – и Google Earth создаст у вас иллюзию, что двойным щелчком мыши можно&lt;br /&gt;
вмешаться в это событие и наблюдать наступивший хаос. Google Earth будит желание поохотиться за метеоритными кратерами или найти исток Амазонки. Бесплатный ресурс такой мощи просто не за что критиковать.&lt;/div&gt;</summary>
		<author><name>Skryabin yuri</name></author>	</entry>

	<entry>
		<id>http://wiki.linuxformat.ru/wiki/%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:Skryabin_yuri</id>
		<title>Участник:Skryabin yuri</title>
		<link rel="alternate" type="text/html" href="http://wiki.linuxformat.ru/wiki/%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:Skryabin_yuri"/>
				<updated>2008-03-18T05:29:23Z</updated>
		
		<summary type="html">&lt;p&gt;Skryabin yuri: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Скрябин Юрий ==&lt;br /&gt;
[[LXF84|LXF84]]&lt;br /&gt;
&lt;br /&gt;
[[LXF85|LXF85]]&lt;br /&gt;
&lt;br /&gt;
[[LXF86|LXF86]]&lt;br /&gt;
&lt;br /&gt;
[[LXF87-88|LXF87/88]]&lt;/div&gt;</summary>
		<author><name>Skryabin yuri</name></author>	</entry>

	<entry>
		<id>http://wiki.linuxformat.ru/wiki/%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:Skryabin_yuri</id>
		<title>Участник:Skryabin yuri</title>
		<link rel="alternate" type="text/html" href="http://wiki.linuxformat.ru/wiki/%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:Skryabin_yuri"/>
				<updated>2008-03-18T05:28:03Z</updated>
		
		<summary type="html">&lt;p&gt;Skryabin yuri: Новая: == Скрябин Юрий == LXF84  LXF85  LXF86  LXF87/88&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Скрябин Юрий ==&lt;br /&gt;
[[LXF84|LXF84]]&lt;br /&gt;
&lt;br /&gt;
[[LXF85|LXF85]]&lt;br /&gt;
&lt;br /&gt;
[[LXF86|LXF86]]&lt;br /&gt;
&lt;br /&gt;
[[LXF87/88|LXF87/88]]&lt;/div&gt;</summary>
		<author><name>Skryabin yuri</name></author>	</entry>

	<entry>
		<id>http://wiki.linuxformat.ru/wiki/LXF84:%D0%A7%D1%82%D0%BE_%D0%B7%D0%B0_%D1%88%D1%82%D1%83%D0%BA%D0%B0...</id>
		<title>LXF84:Что за штука...</title>
		<link rel="alternate" type="text/html" href="http://wiki.linuxformat.ru/wiki/LXF84:%D0%A7%D1%82%D0%BE_%D0%B7%D0%B0_%D1%88%D1%82%D1%83%D0%BA%D0%B0..."/>
				<updated>2008-03-17T13:55:05Z</updated>
		
		<summary type="html">&lt;p&gt;Skryabin yuri: Новая: == Что за штука... Java Server Faces? == '''''Ричард Драммонд''' прослышал о более простом и быстром способе строител...&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Что за штука... Java Server Faces? ==&lt;br /&gt;
'''''Ричард Драммонд''' прослышал о более простом и быстром способе строительства web-приложений. Определенно стоит разобраться…''&lt;br /&gt;
&lt;br /&gt;
'''Сейчас много шумят об этой новой web-технологии, JavaServer Faces. Для чего она?'''&lt;br /&gt;
&lt;br /&gt;
JavaServer Faces (сокращенно JSF) – компонентная платформа, призванная упростить разработку пользовательских интерфейсов для web-приложений Java. Это…&lt;br /&gt;
&lt;br /&gt;
'''Секундочку. У нас уже есть Struts, Tapestry, WebWork и nauseam. Зачем создавать еще одну платформу для Java-приложений?'''&lt;br /&gt;
&lt;br /&gt;
В том-то и часть проблемы: много несовместимых платформ. Однако JSF – открытый стандарт, разрабатываемый в рамках Java Community Process, и представители многих популярных, но нестандартных платформ внесли свою лепту в разработку спецификации JSF (текущая версия JSF 1.2). Спецификация открытая, и применять ее может каждый. Sun, кстати, выпустила стандартную реализацию.&lt;br /&gt;
&lt;br /&gt;
'''Ясно. Но чем JSF отличается от, скажем, Jakarta Struts?'''&lt;br /&gt;
&lt;br /&gt;
Тем, что у этих проектов разные цели. Struts – завершенная платформа, позволяющая упростить построение Java-приложений с использованием парадигмы модель-вид-контроллер (MVC). JSF сосредоточена на одной части парадигмы, виде.&lt;br /&gt;
&lt;br /&gt;
'''Вид — то есть вид web-приложений, отсюда и «Faces»?'''&lt;br /&gt;
&lt;br /&gt;
Точно. MVC – программная архитектура, четко разделяющая пользовательское приложение на три части: Модель (часть программы, содержащая данные), Вид (представление данных, позволяющее пользователю взаимодействовать с программой) и Управление (обработка событий, например, пользовательского ввода, и обновление в соответствии с этими событиями Модели и/или Вида). Архитектура MVC успешно используется некоторыми современными средами разработки, включая Cocoa для Mac OS X, Microsoft Foundation Classes и Swing для Java.&lt;br /&gt;
Теперь наблюдается, что подобный подход начал применяться и к web-приложениям, отсюда и популярность Struts.&lt;br /&gt;
&lt;br /&gt;
'''Спасибо за объяснение технологии, но что MVC даст лично мне?'''&lt;br /&gt;
&lt;br /&gt;
Если рассматривать приложение таким образом, можно отделить модель от вида. Это особенно актуально для web-приложений. Вспомните только, как часто популярные сайты подвергаются визуальному обновлению (меняется вид), а обрабатываемые ими данные (модель) остаются неизменными. Кроме того, в web-разработках и у программиста, и у дизайнера (который не обязательно разбирается в программировании) должна быть возможность трудиться над приложением вместе. Наконец, вам могут понадобиться различные методы доставки web-приложения пользователям: скажем, вы работаете с HTML-интерфейсом для настольных компьютеров, а с WML – для мобильных устройств. Благодаря MVC решение этих задач существенно упрощается.&lt;br /&gt;
&lt;br /&gt;
'''Если JSF занимается только видом, чем она лучше Struts, которая умеет все?'''&lt;br /&gt;
&lt;br /&gt;
Не обязательно быть во всем лучше всех. JSF лучше только для построения пользовательских интерфейсов. Вполне возможно совместное использование Struts и JSF в одном приложении – есть даже дочерний проект Struts под названием Shale, для более плотной интеграции с JSF (см. http://shale.apache.org).&lt;br /&gt;
&lt;br /&gt;
'''Об этом хватит! Расскажите подробнее о JSF.'''&lt;br /&gt;
&lt;br /&gt;
Вижу, вас надо хорошенько убедить. Ладно. Иногда JSF называют «Swing для web-приложений», и это правильно (как известно, Swing – стандартная среда разработки графических пользовательских интерфейсов, GUI, на чистом Java). Со Swing легко изменять способы отображения компонентов интерфейса или создавать особые компоненты, а также использовать визуальные редакторы интерфейсов. Все эти преимущества применимы к JSF, но не к Struts.&lt;br /&gt;
&lt;br /&gt;
'''Вы приводите сравнение со Swing. Это, повашему, убедительно?'''&lt;br /&gt;
&lt;br /&gt;
Да забудьте вы эту Swing-фобию! Ведь вы же сможете строить интерфейс web-приложения так же легко, как строится простой GUI – перетаскиванием компонентов в UI-конструктор; это ли не здорово?&lt;br /&gt;
&lt;br /&gt;
'''Допустим. Но интерфейс для web и для обычных платформ – не одно и то же. Осуществима ли эта идея?'''&lt;br /&gt;
&lt;br /&gt;
Да, поскольку JSF моделирует интерфейсы точно так же, как традиционные среды разработки, в частности, Swing. В основе JSF лежит API, позволяющий создавать компоненты интерфейса, не зависящие от устройства вывода. Этот API управляет всеми вопросами, связанными с пользовательским интерфейсом: жизненным циклом, обработкой событий, персистентностью (способность сохранять и поддерживать объекты) и навигацией. JSF предоставляет также базовый набор компонентов GUI, знакомых дизайнеру любых интерфейсов.&lt;br /&gt;
&lt;br /&gt;
'''Как это отразится на HTML-интерфейсе, который я вижу в браузере?'''&lt;br /&gt;
&lt;br /&gt;
Основные компоненты интерфейса JSF существуют на серверной стороне приложения и не зависят от средств представления. Однако нынешняя спецификация JSF требует применения рендерера, способного отображать компоненты пользовательского интерфейса как HTML, через JavaServer Pages (JSP). Возможны и другие технологии представления, но поддержка JSP обязательна. &lt;br /&gt;
&lt;br /&gt;
'''Погодите продолжать, поясните, пожалуйста, что такое JavaServer Pages?'''&lt;br /&gt;
&lt;br /&gt;
С удовольствием. Основа технологии генерации динамического web-контента с сервера Java-приложений – это сервлет. Но строительство пользовательского интерфейса только через сервлеты весьма проблематично: встраивать весь генерируемый контент (в основном HTML) внутрь Java-кода – задача непосильная. Поэтому и появилась JavaServer Pages. Теперь все наоборот: можно добавить в HTML особые тэги, исполняющие необходимый для генерации динамического контента Java-код, а то и встроить этот код непосредственно в HTML-страницу.&lt;br /&gt;
&lt;br /&gt;
'''А применение JSF обязательно требует поддержки JSP?'''&lt;br /&gt;
&lt;br /&gt;
Да, поставляется библиотека тэгов JSP с особыми тэгами, позволяющими оперировать с компонентами пользовательского интерфейса JSF. Например, если вы хотите представить пользователю данные в виде таблицы, нужно воспользоваться соответствующим JSF-тэгом. JSF возьмет на себя генерацию таблицы в виде HTML-кода в ответ на пользовательский запрос, а web-контейнер доставит ее в браузер пользователя.&lt;br /&gt;
&lt;br /&gt;
'''Полагаю, ввод данных в страницы JSF не составит труда…'''&lt;br /&gt;
&lt;br /&gt;
К сожалению, избежать Java-кодирования не получится. Каждая страница JSF связана с «бином» (bean), который передает значения компонентам JSF, занимается обработкой событий, проверкой введенных данных и т.п. Каждый компонент JSF связывается со свойствами и методами «бина» через атрибуты тэгов JSF&lt;br /&gt;
 &lt;br /&gt;
'''ОК, вы заинтриговали меня. С чего же начать разработку в JSF?'''&lt;br /&gt;
&lt;br /&gt;
Можно начать разработку с помощью web-контейнера типа Tomcat, вручную инсталлировать экземпляр JSF, затем в простом текстовом редакторе создать шаблоны и необходимый Java-код. Однако простейший путь – зарегистрироваться в Sun Developer Network и&lt;br /&gt;
установить новейшую версию Sun Studio Creator (см. http://developers.sun.com/prodtech/javatools/jscreator). Это полный пакет для JSF-разработки, включающий Java IDE, визуальный конструктор и сервер приложений. Регистрация свободная, а загрузка Creator для&lt;br /&gt;
зарегистрированных членов бесплатна.&lt;br /&gt;
&lt;br /&gt;
'''Хм. А нет ли других решений среди свободного ПО?'''&lt;br /&gt;
&lt;br /&gt;
Creator от Sun основывается на открытом NetBeans IDE, но в текущей стабильной версии NetBeans еще нет визуальных инструментов для работы с JSF. &lt;br /&gt;
&lt;br /&gt;
'''Вы сказали, что JSF – открытый стандарт. Нет ли других вариантов, кроме как от Sun?'''&lt;br /&gt;
&lt;br /&gt;
Конечно, есть: например, Apache MyFaces (см. http://myfaces. apache.org).&lt;br /&gt;
&lt;br /&gt;
'''Хотелось бы познакомиться с библиотеками компонентов JSF.'''&lt;br /&gt;
&lt;br /&gt;
Отлично! Попробуйте ADF Faces от Oracle (http://www.oracle.com/technology/products/jdev/htdocs/partners/addins/exchange/jsf).&lt;br /&gt;
&lt;br /&gt;
'''А где можно подробнее узнать о JavaServer Pages?'''&lt;br /&gt;
&lt;br /&gt;
Рекомендую http://java.sun.com/javaee/javaserverfaces. Там можно найти информацию и ссылки на многочисленные статьи и руководства по JSF.&lt;/div&gt;</summary>
		<author><name>Skryabin yuri</name></author>	</entry>

	<entry>
		<id>http://wiki.linuxformat.ru/wiki/Linuxformat:%D0%9F%D0%BE%D1%80%D1%82%D0%B0%D0%BB_%D1%81%D0%BE%D0%BE%D0%B1%D1%89%D0%B5%D1%81%D1%82%D0%B2%D0%B0</id>
		<title>Linuxformat:Портал сообщества</title>
		<link rel="alternate" type="text/html" href="http://wiki.linuxformat.ru/wiki/Linuxformat:%D0%9F%D0%BE%D1%80%D1%82%D0%B0%D0%BB_%D1%81%D0%BE%D0%BE%D0%B1%D1%89%D0%B5%D1%81%D1%82%D0%B2%D0%B0"/>
				<updated>2008-03-17T11:41:03Z</updated>
		
		<summary type="html">&lt;p&gt;Skryabin yuri: Учебник Java выполнено&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Обязательно к прочтению: [[Информация для авторов]]&lt;br /&gt;
{| class=&amp;quot;standart&amp;quot;&lt;br /&gt;
|+Координационная таблица (красных ссылок)&lt;br /&gt;
|-&lt;br /&gt;
! ||Январь||Февраль||Март||Апрель||Май||Июнь||Июль||Август||Сентябрь||Октябрь||Ноябрь||Декабрь&lt;br /&gt;
|-&lt;br /&gt;
! 2005&lt;br /&gt;
| || || || || || || ||&lt;br /&gt;
| [[LXF70]]&lt;br /&gt;
| [[LXF71]]&lt;br /&gt;
| [[LXF72]]&lt;br /&gt;
| [[LXF73]]&lt;br /&gt;
|-&lt;br /&gt;
! 2006&lt;br /&gt;
| [[LXF74-75]]&lt;br /&gt;
| [[LXF76]]&lt;br /&gt;
| [[LXF77]]&lt;br /&gt;
| [[LXF78]]&lt;br /&gt;
| [[LXF79]]&lt;br /&gt;
| [[LXF80]]&lt;br /&gt;
| [[LXF81]]&lt;br /&gt;
| [[LXF82]]&lt;br /&gt;
| [[LXF83]]&lt;br /&gt;
| [[LXF84]]&lt;br /&gt;
| [[LXF85]]&lt;br /&gt;
| [[LXF86]]&lt;br /&gt;
|-&lt;br /&gt;
! 2007&lt;br /&gt;
| [[LXF87-88]]&lt;br /&gt;
| [[LXF89]]&lt;br /&gt;
| [[LXF90]]&lt;br /&gt;
| [[LXF91]]&lt;br /&gt;
| [[LXF92]]&lt;br /&gt;
| [[LXF93]]&lt;br /&gt;
| [[LXF94]]&lt;br /&gt;
| [[LXF95]]&lt;br /&gt;
| [[LXF96]]&lt;br /&gt;
| [[LXF97]]&lt;br /&gt;
| [[LXF98]]&lt;br /&gt;
| [[LXF99]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
Следующие номера Linux Format являются &amp;quot;занятыми&amp;quot; &amp;amp;ndash; т.е. для них уже нашелся человек, желающий конвертировать их в формат Wiki:&lt;br /&gt;
&lt;br /&gt;
# [[LXF70|Linux Format 70, Сентябрь 2005]] [[Изображение:75%.png]]&lt;br /&gt;
# [[LXF71|Linux Format 71, Октябрь 2005]] [[Изображение:00%.png]]&lt;br /&gt;
# [[LXF72|Linux Format 72, Ноябрь 2005]] [[Изображение:25%.png]]&lt;br /&gt;
# [[LXF73|Linux Format 73, Декабрь 2005]] [[Изображение:25%.png]]&lt;br /&gt;
# [[LXF74-75|Linux Format 74-75, Январь 2006]] [[Изображение:00%.png]]&lt;br /&gt;
# [[LXF76|Linux Format 76, Февраль 2006]] [[Изображение:00%.png]]&lt;br /&gt;
# [[LXF77|Linux Format 77, Март 2006]] [[Изображение:25%.png]]&lt;br /&gt;
# [[LXF78|Linux Format 78, Апрель 2006]] [[Изображение:25%.png]]&lt;br /&gt;
# [[LXF79|Linux Format 79, Май 2006]] [[Изображение:25%.png]]&lt;br /&gt;
# [[LXF80|Linux Format 80, Июнь 2006]] [[Изображение:00%.png]]&lt;br /&gt;
# [[LXF81|Linux Format 81, Июль 2006]] [[Изображение:75%.png]]&lt;br /&gt;
# [[LXF82|Linux Format 82, Август 2006]] [[Изображение:25%.png]]&lt;br /&gt;
# [[LXF83|Linux Format 83, Сентябрь 2006]] [[Изображение:50%.png]]&lt;br /&gt;
# [[LXF84|Linux Format 84, Октябрь 2006]] [[Изображение:25%.png]]&lt;br /&gt;
# [[LXF85|Linux Format 85, Ноябрь 2006]] [[Изображение:25%.png]]&lt;br /&gt;
# [[LXF86|Linux Format 86, Декабрь 2006]] [[Изображение:25%.png]]&lt;br /&gt;
# [[LXF87-88|Linux Format 87-88, Январь 2007]] [[Изображение:00%.png]]&lt;br /&gt;
# [[LXF89|Linux Format 89, Февраль 2007]] [[Изображение:75%.png]]&lt;br /&gt;
# [[LXF90|Linux Format 90, Март 2007]] [[Изображение:25%.png]]&lt;br /&gt;
# [[LXF91|Linux Format 91, Апрель 2007]] [[Изображение:25%.png]]&lt;br /&gt;
# [[LXF92|Linux Format 92, Май 2007]] [[Изображение:00%.png]]&lt;br /&gt;
# [[LXF93|Linux Format 93, Июнь 2007]] [[Изображение:25%.png]]&lt;br /&gt;
# [[LXF94|Linux Format 94, Июль 2007]] [[Изображение:25%.png]]&lt;br /&gt;
# [[LXF95|Linux Format 95, Август 2007]] [[Изображение:25%.png]]&lt;br /&gt;
# [[LXF96|Linux Fromat 96, Сентябрь 2007]] [[Изображение:25%.png]]&lt;br /&gt;
# [[LXF97|Linux Format 97, Октябрь 2007]] [[Изображение:25%.png]]&lt;br /&gt;
# [[LXF98|Linux Format 98, Ноябрь 2007]] [[Изображение:25%.png]]&lt;br /&gt;
# [[LXF99|Linux Format 99, Декабрь 2007]] [[Изображение:25%.png]]&lt;br /&gt;
&lt;br /&gt;
Следующие материалы или серии материалов также являются &amp;quot;занятыми&amp;quot;:&lt;br /&gt;
* Учебник Java, LXF84-LXF87/88 &amp;amp;ndash; выполнено&lt;br /&gt;
* Учебник Subversion ([[LXF70:Subversion1|части 1]],[[LXF70:Subversion2|2]]), LXF70 &amp;amp;ndash; выполнено&lt;br /&gt;
&lt;br /&gt;
Для пробы wiki-разметки: [[Песочница]]&lt;/div&gt;</summary>
		<author><name>Skryabin yuri</name></author>	</entry>

	<entry>
		<id>http://wiki.linuxformat.ru/wiki/LXF87-88:Java</id>
		<title>LXF87-88:Java</title>
		<link rel="alternate" type="text/html" href="http://wiki.linuxformat.ru/wiki/LXF87-88:Java"/>
				<updated>2008-03-17T11:29:51Z</updated>
		
		<summary type="html">&lt;p&gt;Skryabin yuri: Взаимные блокировки&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=== Потоки в Java ===&lt;br /&gt;
''ЧАСТЬ 4: Завершая курс молодого Java-бойца, '''Антон Черноусов''' научит вас управлять потоками... Жаль, что не денежными.''&lt;br /&gt;
&lt;br /&gt;
C каждым днем появляются все более мощные процессоры, многоядерная архитектура которых стала основной темой ушедшего года, поэтому двухядерный процессор в ноутбуке уже никого не удивляет. С одной стороны – это обстоятельство приближает возможности простого пользователя к возможностям «понастоящему» больших систем. С другой (и рекламные буклеты об этом обычно молчат) – для того, чтобы использовать весь потенциал современных компьютеров, приложение должно «уметь» просчитать задачу фактически на двух или более процессорах. &lt;br /&gt;
&lt;br /&gt;
Создание эффективных алгоритмов для работы на многопроцессорных станциях – это большая и сложная работа. Несмотря на это, для любого программиста актуальна задача организации взаимодействия с медленными ресурсами (например, чтения, записи или копирования файлов, работы с принтером, сетью), так как немногие пользователи смирятся с тем, что их любимая программа «замирает» в момент выполнения какой-либо операции.&lt;br /&gt;
&lt;br /&gt;
Во избежание описанных проблем программа должна использовать потоки или процессы. Под процессом понимается заявка на потребле-&lt;br /&gt;
ние всех видов ресурсов системы, кроме одного – процессорного времени, или иначе говоря, процесс – это запущенная на выполнение программа (такое определение дается в [[LXF87/88:Java#Литература|[1]]]). Поток рассматривается как самостоятельная активность внутри процесса, хотя существуют другие трактовки этого понятия, которые зависят от используемой операционной системы (см., например, [[LXF87/88:Java#Литература|[2]]]). Поток получил свое название по аналогии с потоком команд, поступающих в процессор; при выполнении потоки делят адресное пространство и выделенную память внутри одного процесса. Процессорное время распределяется между различными потоками операционной системой, точнее, одним из компонентов ее ядра – планировщиком. Более полно с понятием процессов и потоков и механизмов работы с ними с точки зрения операционной системы вы можете ознакомиться в книге [[LXF87/88:Java#Литература|[3]]]. &lt;br /&gt;
&lt;br /&gt;
Давайте завершим наш экскурс в теорию и окунемся в реальность Java. Под процессом здесь принято понимать всеобъемлющий контекст выполнения, обеспечивающий высокий уровень изоляции охватываемых им данных от внешнего мира, а под потоком – более «легковесный» активный агент; в контексте одного процесса может функционировать целое множество потоков [[LXF87/88:Java#Литература|[4]]]. Планирование потоков в Java обеспечивается внутренними механизмами JVM.&lt;br /&gt;
&lt;br /&gt;
=== Поток, он же thread ===&lt;br /&gt;
В Java существует два способа работы с потоками: первый заключается в реализации интерфейса Runnable, второй связан с наследованием&lt;br /&gt;
класса Thread, который уже реализует данный интерфейс. В обоих случаях класс должен предоставлять реализацию метода run(). Ниже&lt;br /&gt;
приведен пример класса, реализующего поток через наследование класса Thread:&lt;br /&gt;
&amp;lt;source lang = &amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
public class FirstThread extends Thread {&lt;br /&gt;
  public void run(){&lt;br /&gt;
    for (int i = 1 ; i &amp;lt; 30; i++)&lt;br /&gt;
      System.out.println(&amp;quot;It is in thread &amp;quot;+ i);&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Собственно, метод run() и должен содержать некоторый набор инструкций (разумеется, на языке Java), которые вы хотите выполнить&lt;br /&gt;
в отдельном потоке. Например, если вы реализуете функцию копирования файла (а пользователь, скажем, копирует ISO-образ объемом&lt;br /&gt;
600 Мб), желательно, чтобы эта операция выполнялась в отдельном потоке, запуск которого можно производить следующим образом:&lt;br /&gt;
&amp;lt;source lang = &amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
public class ConsoleToThread {&lt;br /&gt;
  public static void main(String[] args) {&lt;br /&gt;
    FirstThread thread = new FirstThread();&lt;br /&gt;
    thread.start();&lt;br /&gt;
    for (int i = 1; i &amp;lt; 20; i++) {&lt;br /&gt;
      System.out.println(&amp;quot;It is in main &amp;quot; + i);&lt;br /&gt;
    }&lt;br /&gt;
    try {&lt;br /&gt;
      thread.join();&lt;br /&gt;
    } &lt;br /&gt;
    catch (InterruptedException ex) {&lt;br /&gt;
      System.out.println(&amp;quot;Exception in stop thread&amp;quot;);&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
При выполнении метода main() класса ConsoleToThread создается объект-поток FirstThread, который запускается на выполнение методом start() [заметьте – метод run() никогда не вызывается явно, – прим.ред.]. Метод join() используется в случае, когда необходимо «дождаться» завершения потока. Завершение работы потока происходит при выходе из метода run(), как явном (например, посредством return), так и неявном (если внутри метода возникло и не было обработано какое-то исключение).&lt;br /&gt;
&lt;br /&gt;
Имейте в виду (это важно!): повторный запуск уже отработавшего потока приведет к исключению IllegalThreadStateException.&lt;br /&gt;
&lt;br /&gt;
=== Реализация потока через Runnable ===&lt;br /&gt;
Давайте теперь рассмотрим пример работы с потоками через интерфейс Runnable. Если, допустим, класс SameRunnable реализует интерфейс Runnable, то запустить поток на основе этого класса на выполнение можно следующим образом:&lt;br /&gt;
&amp;lt;source lang = &amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
Runnable run = new SameRunnable();&lt;br /&gt;
Thread thread = new Thread(run);&lt;br /&gt;
thread.start();&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
В следующем примере в методе main() класса ConsoleToThreadTwo создается массив threadArray, состоящий из объектов-потоков. При&lt;br /&gt;
этом используется конструктор класса Thread, принимающий два параметра: ссылку на объект, реализующий интерфейс Runnable и&lt;br /&gt;
имя потока:&lt;br /&gt;
&amp;lt;source lang = &amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
Thread thread = new Thread(Runnable, ThreadName);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Метод getName() объекта, реализующего поток, возвращает указанное при создании имя. Обратите внимание, что в нем используется&lt;br /&gt;
статический метод Thread.currentThread(), возвращающий ссылку на объект Thread, соответствующий выполняющемуся в текущий момент&lt;br /&gt;
потоку:&lt;br /&gt;
&amp;lt;source lang = &amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
public class SecondThread implements Runnable {&lt;br /&gt;
  public String getName() {&lt;br /&gt;
    return Thread.currentThread().getName();&lt;br /&gt;
  }&lt;br /&gt;
  public void run() {&lt;br /&gt;
    for (int i = 1; i &amp;lt; 100000; i++) {&lt;br /&gt;
      if ((i % 10000) == 0) {&lt;br /&gt;
        System.out.println(getName() + &amp;quot; counts &amp;quot; + i / 10000);&lt;br /&gt;
      }&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
public class ConsoleToThreadTwo {&lt;br /&gt;
  public static void main(String[] args) {&lt;br /&gt;
    Thread[] threadArray = new Thread[3];&lt;br /&gt;
      for (int i=0; i&amp;lt;threadArray.length; i++){&lt;br /&gt;
        threadArray[i] = new Thread(new SecondThread(), &amp;quot;Thread &amp;quot; + i);&lt;br /&gt;
      }&lt;br /&gt;
      for (int i=0; i&amp;lt;threadArray.length; i++){&lt;br /&gt;
        threadArray[i].start();&lt;br /&gt;
        System.out.println(threadArray[i].getName() + &amp;quot; started&amp;quot;);&lt;br /&gt;
      }&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Проследив за выводом этой программы, можно заметить, что процессорное время распределяется между потоками практически равномерно, однако порядок их выполнения во многом случаен.&lt;br /&gt;
&lt;br /&gt;
=== Приоритеты потоков ===&lt;br /&gt;
Для управления величиной процессорного времени, выделяемого потоку, можно воспользоваться приоритетами. Установка приоритетов происходит с помощью метода Thread.setPriority(), узнать текущий приоритет позволяет метод getPriority(). В классе Thread определены&lt;br /&gt;
три константы:&lt;br /&gt;
&amp;lt;source lang = &amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
MIN_PRIORITY = 1&lt;br /&gt;
NORM_PRIORITY = 5&lt;br /&gt;
MAX_PRIORITY = 10&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Важно понимать, что значение приоритета потока предназначено для Java-машины и не соответствует реальным приоритетам потоков&lt;br /&gt;
в операционной системе.&lt;br /&gt;
&lt;br /&gt;
Давайте немного изменим код метода main() класса ConsoleToThreadTwo:&lt;br /&gt;
&amp;lt;source lang = &amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
public static void main(String[] args) {&lt;br /&gt;
  Thread[] threadArray = new Thread[3];&lt;br /&gt;
  int pr = 0;&lt;br /&gt;
  for (int i=0; i&amp;lt;threadArray.length; i++){&lt;br /&gt;
    threadArray[i] = new Thread(new SecondThread(), &amp;quot;Thread &amp;quot; + i);&lt;br /&gt;
    if (pr == 10) &lt;br /&gt;
      pr = 0; &lt;br /&gt;
    threadArray[i].setPriority(Thread.MIN_PRIORITY + pr);&lt;br /&gt;
    pr++;&lt;br /&gt;
  }&lt;br /&gt;
  for (int i=0; i&amp;lt;threadArray.length; i++){&lt;br /&gt;
    threadArray[i].start();&lt;br /&gt;
    System.out.println(threadArray[i].getName() + &amp;quot; started&amp;quot;);&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Анализ результатов работы класса показывает, что потоки, получившие более высокий приоритет, выполняются чаще. Также, благодаря&lt;br /&gt;
условию на значение переменной pr, setPriority() никогда не будет передан приоритет, превышающий 10 (MAX_PRIORITY). Если бы это про-&lt;br /&gt;
изошло, система выбросила бы исключение IllegalArgumentException.&lt;br /&gt;
&lt;br /&gt;
=== Потоки-демоны ===&lt;br /&gt;
Сделаем еще одно важное замечание: программа будет выполняться до тех пор, пока выполняется хотя бы один запущенный в ней поток;&lt;br /&gt;
единственным исключением являются потоки-демоны.&lt;br /&gt;
&lt;br /&gt;
Что же это такое? Демон отличается от «простого смертного» потока вызовом метода setDeamon(true), который необходимо сделать до&lt;br /&gt;
начала работы. Например, так:&lt;br /&gt;
&amp;lt;source lang = &amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
FirstThread thread = new FirstThread();&lt;br /&gt;
thread.setDeamon(true);&lt;br /&gt;
thread.start();&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Узнать, является ли поток демоном, можно с помощью метода isDeamon(). Обычно потоки-демоны создаются для обслуживания&lt;br /&gt;
некритичных задач, так как при завершении работы программа не дожидается их остановки, а прерывает их самостоятельно.&lt;br /&gt;
&lt;br /&gt;
=== Где искать потоки? ===&lt;br /&gt;
В большинстве случаев бывает необходимо отслеживать ранее запущенные на выполнение потоки. Использование массива потоков,&lt;br /&gt;
как в предыдущем примере, не всегда оправданно. Для хранения и обработки потоков в Java существует класс ThreadGroup. Группа,&lt;br /&gt;
к которой принадлежит создаваемый поток, опять-таки передается конструктору Thread():&lt;br /&gt;
&amp;lt;source lang = &amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
ThreadGroup tg = new ThreadGroup(&amp;quot;NameThreadGroup&amp;quot;);&lt;br /&gt;
Thread thread = new Thread(tg, new SecondThread(), &amp;quot;ThreadName&amp;quot;);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Если группа не указана явно, поток будет помещен в тот же ThreadGroup, что и его родитель.&lt;br /&gt;
&amp;lt;source lang = &amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
ThreadGroup tg = new ThreadGroup(&amp;quot;NameThreadGroup&amp;quot;);&lt;br /&gt;
Thread thread = new Thread(tg, new SecondThread(), &amp;quot;ThreadName&amp;quot;);&lt;br /&gt;
Thread thread1 = new Thread(tg, new SecondThread(), &amp;quot;ThreadName2&amp;quot;);&lt;br /&gt;
Thread thread2 = new Thread(tg, new SecondThread(), &amp;quot;ThreadName3&amp;quot;);&lt;br /&gt;
System.out.println(&amp;quot;active thread in group &amp;quot; + tg.activeCount());&lt;br /&gt;
thread.start();&lt;br /&gt;
thread1.start();&lt;br /&gt;
System.out.println(&amp;quot;active thread in group &amp;quot; + tg.activeCount());&lt;br /&gt;
Thread[] threads = new Thread[tg.activeCount()];&lt;br /&gt;
int m = tg.enumerate(threads);&lt;br /&gt;
System.out.println(&amp;quot;taked threads from group : &amp;quot; + m);&lt;br /&gt;
for (int i = 0; i &amp;lt; threads.length; i++) {&lt;br /&gt;
  System.out.println(threads[i].getName());&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
В представленном выше примере в экземпляр класса ThreadGroup помещаются три потока, два из которых запускаются на выполнение.&lt;br /&gt;
Количество активных потоков в группе определяется с помощью метода activeCount(), а в результате выполнения метода enumerate() формируется перечень всех активных потоков.&lt;br /&gt;
&lt;br /&gt;
=== Управление потоками ===&lt;br /&gt;
При запуске потоков следует учитывать и то, что их иногда приходится останавливать, причем как штатно, так и экстренно. Для того, чтобы&lt;br /&gt;
приостановить работу потока изнутри, допустим, в тот момент, когда закончилась доступные для обработки данные, можно использовать&lt;br /&gt;
два метода: sleep() и wait().&lt;br /&gt;
&amp;lt;source lang = &amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
public class ThirdThread extends Thread {&lt;br /&gt;
  public void run() {&lt;br /&gt;
    for (int i = 1; i &amp;lt; 110; i++) {&lt;br /&gt;
      if (i == 10) {&lt;br /&gt;
        try {&lt;br /&gt;
          sleep(10000);&lt;br /&gt;
        } &lt;br /&gt;
        catch (InterruptedException e) {&lt;br /&gt;
          System.out.println(&amp;quot;the thread was awaken there (just a moment ago)&amp;quot;);&lt;br /&gt;
        }&lt;br /&gt;
      }&lt;br /&gt;
      if (i == 100) {&lt;br /&gt;
        try {&lt;br /&gt;
          synchronized (this) { wait();}&lt;br /&gt;
        }&lt;br /&gt;
        catch (InterruptedException e) {&lt;br /&gt;
          System.out.println(&amp;quot;the thread was awaken there (just a moment ago)again&amp;quot;);&lt;br /&gt;
        }&lt;br /&gt;
      } &lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Методу sleep() передается переменная типа long, соответствующая количеству миллисекунд, в течении которых поток будет «спать». В&lt;br /&gt;
случае wait() поток ждет пробуждения снаружи. Применение методов sleep() и wait() требует обработки исключительной ситуации, которая возникают при пробуждении потока. В представленном ниже классе ConsoleToThreadThree потоки пробуждаются с помощью метода interrupt():&lt;br /&gt;
&amp;lt;source lang = &amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
public class ConsoleToThreadThree {&lt;br /&gt;
  public static void main(String[] args) {&lt;br /&gt;
    ThirdThread thread = new ThirdThread();&lt;br /&gt;
    thread.start();&lt;br /&gt;
    for (int i = 1; i &amp;lt; 20; i++) {&lt;br /&gt;
      System.out.println(&amp;quot;It is in main &amp;quot; + i);&lt;br /&gt;
    }&lt;br /&gt;
    thread.interrupt();&lt;br /&gt;
    for (int i = 1; i &amp;lt; 20; i++) {&lt;br /&gt;
      System.out.println(&amp;quot;It is in main &amp;quot; + i);&lt;br /&gt;
    }&lt;br /&gt;
    thread.interrupt();&lt;br /&gt;
    try {&lt;br /&gt;
      thread.join();&lt;br /&gt;
    } &lt;br /&gt;
    catch (InterruptedException ex) {&lt;br /&gt;
      System.out.println(&amp;quot;Exception in stop thread&amp;quot;);&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Отметим, что вызов метода wait() без блока синхронизации (synchronized), о котором мы поговорим чуть ниже, приводит к исключению IllegalMonitorStateException. Возникшая ошибка свидетельствует об отсутствии монитора у объекта (понятие монитора и синхронизация&lt;br /&gt;
тесно связаны, о чем мы тоже поговорим ниже). Если для приостановления потока был применен метод wait(), то для «пробуждения» потока&lt;br /&gt;
можно воспользоваться методом notify() или notifyAll(). Первый пробуждает один случайно выбранный спящий поток, а второй пытается&lt;br /&gt;
пробудить их всех.&lt;br /&gt;
&lt;br /&gt;
Кроме рассмотренных выше методов, иногда бывает целесообразно использовать метод yield(), который приостанавливает работу текущего потока. Метод yield() не переводит поток в режим ожидания, как wait(), но предоставляет другим потокам возможность начать работать&lt;br /&gt;
раньше, чем допустила бы Java-машина [фактически, поток, вызвавший yield() добровольно отдает свой квант процессорного времени, –&lt;br /&gt;
прим. ред.]. Метод yield() статичный, так что прекратить с его помощью работу другого потока не получится.&lt;br /&gt;
&lt;br /&gt;
Методов остановки потоков тоже нет (ранее присутствовали методы stop(), resume(), suspend(), но сейчас они объявлены как «deprecated» –&lt;br /&gt;
то есть нерекомендованными к использованию). На сегодня в Java принят уведомительный стиль остановки потока с помощью пары методов:&lt;br /&gt;
уже известного нам interrupt(), применяемого снаружи, чтобы выставить флаг завершения и метода isInterrupted(), вызываемого изнутри&lt;br /&gt;
потока, чтобы узнать состояние флага, свидетельствующего о том, что «пора закругляться».&lt;br /&gt;
&lt;br /&gt;
=== Мониторы и синхронизация ===&lt;br /&gt;
Что такое «монитор», о котором говорилось выше? Нет, это не дисплей, это – объект, используемый как защелка, то есть в данный момент&lt;br /&gt;
времени владеть монитором может только один поток. В случае, если поток завладел монитором, говорят, что он «вошел» в монитор, а все&lt;br /&gt;
остальные потоки, пытающиеся это сделать, будут заморожены (часто говорят, что они «ждут» монитора) до тех пор, пока владелец монитора&lt;br /&gt;
его не освободит, то есть не покинет.&lt;br /&gt;
&lt;br /&gt;
Если перейти к реалиям Java, то объектов типа монитор в явном виде просто нет! С каждым объектом связан неявный монитор, и чтобы&lt;br /&gt;
завладеть им, необходимо вызвать метод или блок, помеченный ключевым словом synchronized. Как только поток входит в такой блок, он&lt;br /&gt;
завладевает монитором объекта, переданного synchronized в качестве параметра. Так происходит и в классе ThirdThread, однако, в момент&lt;br /&gt;
вызова метода wait(), монитор отпускается. Пример synchronized-метода представлен ниже:&lt;br /&gt;
&amp;lt;source lang = &amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
public synchronized boolean sameCheck() {&lt;br /&gt;
  if (a) {&lt;br /&gt;
    a = false; return true;&lt;br /&gt;
  } &lt;br /&gt;
  else {&lt;br /&gt;
    a = true; &lt;br /&gt;
    return false;&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
В целом, синхронизация – это механизм, обеспечивающий монопольный доступ участка кода к некоторому объекту. Одним из первых&lt;br /&gt;
способов, предложенных для синхронизации работы потоков, были семафоры, концепцию которых описал Дейкстра [Dijkstra] в 1965 году&lt;br /&gt;
(часто говорят, что семафор – это классический синхронизированный примитив). Семафор используется для предоставления доступа к огра-&lt;br /&gt;
ниченному количеству ресурсов. Как правило, у семафора есть две операции: P – занять ресурс и V – освободить ресурс. Он может быть&lt;br /&gt;
реализован следующим образом:&lt;br /&gt;
&amp;lt;source lang = &amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
public class SimpleSemaphore {&lt;br /&gt;
  int counter;&lt;br /&gt;
  public SimpleSemaphore() {&lt;br /&gt;
    this.counter = 1;&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  public synchronized void p() throws InterruptedException {&lt;br /&gt;
    while (counter == 0) {&lt;br /&gt;
      wait();&lt;br /&gt;
    }&lt;br /&gt;
    counter = counter + 1;&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  public synchronized void v() throws InterruptedException {&lt;br /&gt;
    counter = counter - 1;&lt;br /&gt;
    notify();&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Можно, конечно, реализовывать семафоры самостоятельно, но проще воспользоваться специальной библиотекой java.util.concurrent.&lt;br /&gt;
Кроме семафоров, она включает в себя еще много чего интересного. &lt;br /&gt;
&lt;br /&gt;
Отметим, что программа, в принципе, может не использовать ни один из методов синхронизации, обходясь методами wait() и notify().&lt;br /&gt;
&lt;br /&gt;
=== Взаимные блокировки ===&lt;br /&gt;
На этом наш рассказ можно было бы и завершить, но чтобы у вас не сложилось впечатление, что в мире многопоточных приложений все&lt;br /&gt;
так радужно, мы поговорим о неприятных последствиях синхронизации. Как только количество потоков начинает стремительно расти и&lt;br /&gt;
возникает необходимость синхронизированного доступа к ограниченному кругу объектов в различной последовательности, будьте готовы к&lt;br /&gt;
ошибкам типа deadlock – взаимным блокировкам.&lt;br /&gt;
&lt;br /&gt;
Взаимная блокировка – это ошибка, которая лучше всего описывается простой формулой: «Поток A держит монитор a и хочет захватить&lt;br /&gt;
монитор b, а поток B держит монитор b и хочет захватить монитор a». В результате оба засыпают «мертвым сном».&lt;br /&gt;
&lt;br /&gt;
Ошибка очень противная и возникает обычно в нетривиальных алгоритмах. Лечится взаимная блокировка грамотным проектированием и профилактическими мерами, вроде следующей: всегда захватывайте мониторы в одном и том же порядке.&lt;br /&gt;
&lt;br /&gt;
Сегодня мы поговорили о двух способах создания потоков Java, разобрались с приоритетами, познакомились со средствами управления работой потоков и демонами, а также сделали небольшой обзор методов синхронизации. Для того, чтобы начать практическую работу с потоками, этого вполне достаточно. Желающим разобраться во всем этом глубже я рекомендую ознакомится с книгой «Concurrent Programming in Java: Design Principles and Patterns», автором которой является Дуг Ли [Doug Lea] – она считается одной из лучших по данной тематике.&lt;br /&gt;
&lt;br /&gt;
На этом мы заканчиваем обзор основ программирования на Java и в следующий раз поговорим о серверных приложениях – приготовьтесь&lt;br /&gt;
к Java Enterprise Edition!&lt;br /&gt;
&lt;br /&gt;
=== Литература ===&lt;br /&gt;
*1. П. Кью «Использование UNIX», ISBN 5-8275-0019-4&lt;br /&gt;
*2. В.Г. Олифер, Н.А. Олифер «Сетевые операционные системы», ISBN 5-272-00120-6&lt;br /&gt;
*3. Д. Бэкон, Т. Харрис «Операционные системы», ISBN 5-94723-969-8&lt;br /&gt;
*4. М. Фаулер «Архитектура корпоративных программных приложений», ISBN 5-8459-0579-6&lt;/div&gt;</summary>
		<author><name>Skryabin yuri</name></author>	</entry>

	<entry>
		<id>http://wiki.linuxformat.ru/wiki/LXF87-88:Java</id>
		<title>LXF87-88:Java</title>
		<link rel="alternate" type="text/html" href="http://wiki.linuxformat.ru/wiki/LXF87-88:Java"/>
				<updated>2008-03-17T11:25:02Z</updated>
		
		<summary type="html">&lt;p&gt;Skryabin yuri: /* Мониторы и синхронизация */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=== Потоки в Java ===&lt;br /&gt;
''ЧАСТЬ 4: Завершая курс молодого Java-бойца, '''Антон Черноусов''' научит вас управлять потоками... Жаль, что не денежными.''&lt;br /&gt;
&lt;br /&gt;
C каждым днем появляются все более мощные процессоры, многоядерная архитектура которых стала основной темой ушедшего года, поэтому двухядерный процессор в ноутбуке уже никого не удивляет. С одной стороны – это обстоятельство приближает возможности простого пользователя к возможностям «понастоящему» больших систем. С другой (и рекламные буклеты об этом обычно молчат) – для того, чтобы использовать весь потенциал современных компьютеров, приложение должно «уметь» просчитать задачу фактически на двух или более процессорах. &lt;br /&gt;
&lt;br /&gt;
Создание эффективных алгоритмов для работы на многопроцессорных станциях – это большая и сложная работа. Несмотря на это, для любого программиста актуальна задача организации взаимодействия с медленными ресурсами (например, чтения, записи или копирования файлов, работы с принтером, сетью), так как немногие пользователи смирятся с тем, что их любимая программа «замирает» в момент выполнения какой-либо операции.&lt;br /&gt;
&lt;br /&gt;
Во избежание описанных проблем программа должна использовать потоки или процессы. Под процессом понимается заявка на потребле-&lt;br /&gt;
ние всех видов ресурсов системы, кроме одного – процессорного времени, или иначе говоря, процесс – это запущенная на выполнение программа (такое определение дается в [[LXF87/88:Java#Литература|[1]]]). Поток рассматривается как самостоятельная активность внутри процесса, хотя существуют другие трактовки этого понятия, которые зависят от используемой операционной системы (см., например, [[LXF87/88:Java#Литература|[2]]]). Поток получил свое название по аналогии с потоком команд, поступающих в процессор; при выполнении потоки делят адресное пространство и выделенную память внутри одного процесса. Процессорное время распределяется между различными потоками операционной системой, точнее, одним из компонентов ее ядра – планировщиком. Более полно с понятием процессов и потоков и механизмов работы с ними с точки зрения операционной системы вы можете ознакомиться в книге [[LXF87/88:Java#Литература|[3]]]. &lt;br /&gt;
&lt;br /&gt;
Давайте завершим наш экскурс в теорию и окунемся в реальность Java. Под процессом здесь принято понимать всеобъемлющий контекст выполнения, обеспечивающий высокий уровень изоляции охватываемых им данных от внешнего мира, а под потоком – более «легковесный» активный агент; в контексте одного процесса может функционировать целое множество потоков [[LXF87/88:Java#Литература|[4]]]. Планирование потоков в Java обеспечивается внутренними механизмами JVM.&lt;br /&gt;
&lt;br /&gt;
=== Поток, он же thread ===&lt;br /&gt;
В Java существует два способа работы с потоками: первый заключается в реализации интерфейса Runnable, второй связан с наследованием&lt;br /&gt;
класса Thread, который уже реализует данный интерфейс. В обоих случаях класс должен предоставлять реализацию метода run(). Ниже&lt;br /&gt;
приведен пример класса, реализующего поток через наследование класса Thread:&lt;br /&gt;
&amp;lt;source lang = &amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
public class FirstThread extends Thread {&lt;br /&gt;
  public void run(){&lt;br /&gt;
    for (int i = 1 ; i &amp;lt; 30; i++)&lt;br /&gt;
      System.out.println(&amp;quot;It is in thread &amp;quot;+ i);&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Собственно, метод run() и должен содержать некоторый набор инструкций (разумеется, на языке Java), которые вы хотите выполнить&lt;br /&gt;
в отдельном потоке. Например, если вы реализуете функцию копирования файла (а пользователь, скажем, копирует ISO-образ объемом&lt;br /&gt;
600 Мб), желательно, чтобы эта операция выполнялась в отдельном потоке, запуск которого можно производить следующим образом:&lt;br /&gt;
&amp;lt;source lang = &amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
public class ConsoleToThread {&lt;br /&gt;
  public static void main(String[] args) {&lt;br /&gt;
    FirstThread thread = new FirstThread();&lt;br /&gt;
    thread.start();&lt;br /&gt;
    for (int i = 1; i &amp;lt; 20; i++) {&lt;br /&gt;
      System.out.println(&amp;quot;It is in main &amp;quot; + i);&lt;br /&gt;
    }&lt;br /&gt;
    try {&lt;br /&gt;
      thread.join();&lt;br /&gt;
    } &lt;br /&gt;
    catch (InterruptedException ex) {&lt;br /&gt;
      System.out.println(&amp;quot;Exception in stop thread&amp;quot;);&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
При выполнении метода main() класса ConsoleToThread создается объект-поток FirstThread, который запускается на выполнение методом start() [заметьте – метод run() никогда не вызывается явно, – прим.ред.]. Метод join() используется в случае, когда необходимо «дождаться» завершения потока. Завершение работы потока происходит при выходе из метода run(), как явном (например, посредством return), так и неявном (если внутри метода возникло и не было обработано какое-то исключение).&lt;br /&gt;
&lt;br /&gt;
Имейте в виду (это важно!): повторный запуск уже отработавшего потока приведет к исключению IllegalThreadStateException.&lt;br /&gt;
&lt;br /&gt;
=== Реализация потока через Runnable ===&lt;br /&gt;
Давайте теперь рассмотрим пример работы с потоками через интерфейс Runnable. Если, допустим, класс SameRunnable реализует интерфейс Runnable, то запустить поток на основе этого класса на выполнение можно следующим образом:&lt;br /&gt;
&amp;lt;source lang = &amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
Runnable run = new SameRunnable();&lt;br /&gt;
Thread thread = new Thread(run);&lt;br /&gt;
thread.start();&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
В следующем примере в методе main() класса ConsoleToThreadTwo создается массив threadArray, состоящий из объектов-потоков. При&lt;br /&gt;
этом используется конструктор класса Thread, принимающий два параметра: ссылку на объект, реализующий интерфейс Runnable и&lt;br /&gt;
имя потока:&lt;br /&gt;
&amp;lt;source lang = &amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
Thread thread = new Thread(Runnable, ThreadName);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Метод getName() объекта, реализующего поток, возвращает указанное при создании имя. Обратите внимание, что в нем используется&lt;br /&gt;
статический метод Thread.currentThread(), возвращающий ссылку на объект Thread, соответствующий выполняющемуся в текущий момент&lt;br /&gt;
потоку:&lt;br /&gt;
&amp;lt;source lang = &amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
public class SecondThread implements Runnable {&lt;br /&gt;
  public String getName() {&lt;br /&gt;
    return Thread.currentThread().getName();&lt;br /&gt;
  }&lt;br /&gt;
  public void run() {&lt;br /&gt;
    for (int i = 1; i &amp;lt; 100000; i++) {&lt;br /&gt;
      if ((i % 10000) == 0) {&lt;br /&gt;
        System.out.println(getName() + &amp;quot; counts &amp;quot; + i / 10000);&lt;br /&gt;
      }&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
public class ConsoleToThreadTwo {&lt;br /&gt;
  public static void main(String[] args) {&lt;br /&gt;
    Thread[] threadArray = new Thread[3];&lt;br /&gt;
      for (int i=0; i&amp;lt;threadArray.length; i++){&lt;br /&gt;
        threadArray[i] = new Thread(new SecondThread(), &amp;quot;Thread &amp;quot; + i);&lt;br /&gt;
      }&lt;br /&gt;
      for (int i=0; i&amp;lt;threadArray.length; i++){&lt;br /&gt;
        threadArray[i].start();&lt;br /&gt;
        System.out.println(threadArray[i].getName() + &amp;quot; started&amp;quot;);&lt;br /&gt;
      }&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Проследив за выводом этой программы, можно заметить, что процессорное время распределяется между потоками практически равномерно, однако порядок их выполнения во многом случаен.&lt;br /&gt;
&lt;br /&gt;
=== Приоритеты потоков ===&lt;br /&gt;
Для управления величиной процессорного времени, выделяемого потоку, можно воспользоваться приоритетами. Установка приоритетов происходит с помощью метода Thread.setPriority(), узнать текущий приоритет позволяет метод getPriority(). В классе Thread определены&lt;br /&gt;
три константы:&lt;br /&gt;
&amp;lt;source lang = &amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
MIN_PRIORITY = 1&lt;br /&gt;
NORM_PRIORITY = 5&lt;br /&gt;
MAX_PRIORITY = 10&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Важно понимать, что значение приоритета потока предназначено для Java-машины и не соответствует реальным приоритетам потоков&lt;br /&gt;
в операционной системе.&lt;br /&gt;
&lt;br /&gt;
Давайте немного изменим код метода main() класса ConsoleToThreadTwo:&lt;br /&gt;
&amp;lt;source lang = &amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
public static void main(String[] args) {&lt;br /&gt;
  Thread[] threadArray = new Thread[3];&lt;br /&gt;
  int pr = 0;&lt;br /&gt;
  for (int i=0; i&amp;lt;threadArray.length; i++){&lt;br /&gt;
    threadArray[i] = new Thread(new SecondThread(), &amp;quot;Thread &amp;quot; + i);&lt;br /&gt;
    if (pr == 10) &lt;br /&gt;
      pr = 0; &lt;br /&gt;
    threadArray[i].setPriority(Thread.MIN_PRIORITY + pr);&lt;br /&gt;
    pr++;&lt;br /&gt;
  }&lt;br /&gt;
  for (int i=0; i&amp;lt;threadArray.length; i++){&lt;br /&gt;
    threadArray[i].start();&lt;br /&gt;
    System.out.println(threadArray[i].getName() + &amp;quot; started&amp;quot;);&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Анализ результатов работы класса показывает, что потоки, получившие более высокий приоритет, выполняются чаще. Также, благодаря&lt;br /&gt;
условию на значение переменной pr, setPriority() никогда не будет передан приоритет, превышающий 10 (MAX_PRIORITY). Если бы это про-&lt;br /&gt;
изошло, система выбросила бы исключение IllegalArgumentException.&lt;br /&gt;
&lt;br /&gt;
=== Потоки-демоны ===&lt;br /&gt;
Сделаем еще одно важное замечание: программа будет выполняться до тех пор, пока выполняется хотя бы один запущенный в ней поток;&lt;br /&gt;
единственным исключением являются потоки-демоны.&lt;br /&gt;
&lt;br /&gt;
Что же это такое? Демон отличается от «простого смертного» потока вызовом метода setDeamon(true), который необходимо сделать до&lt;br /&gt;
начала работы. Например, так:&lt;br /&gt;
&amp;lt;source lang = &amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
FirstThread thread = new FirstThread();&lt;br /&gt;
thread.setDeamon(true);&lt;br /&gt;
thread.start();&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Узнать, является ли поток демоном, можно с помощью метода isDeamon(). Обычно потоки-демоны создаются для обслуживания&lt;br /&gt;
некритичных задач, так как при завершении работы программа не дожидается их остановки, а прерывает их самостоятельно.&lt;br /&gt;
&lt;br /&gt;
=== Где искать потоки? ===&lt;br /&gt;
В большинстве случаев бывает необходимо отслеживать ранее запущенные на выполнение потоки. Использование массива потоков,&lt;br /&gt;
как в предыдущем примере, не всегда оправданно. Для хранения и обработки потоков в Java существует класс ThreadGroup. Группа,&lt;br /&gt;
к которой принадлежит создаваемый поток, опять-таки передается конструктору Thread():&lt;br /&gt;
&amp;lt;source lang = &amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
ThreadGroup tg = new ThreadGroup(&amp;quot;NameThreadGroup&amp;quot;);&lt;br /&gt;
Thread thread = new Thread(tg, new SecondThread(), &amp;quot;ThreadName&amp;quot;);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Если группа не указана явно, поток будет помещен в тот же ThreadGroup, что и его родитель.&lt;br /&gt;
&amp;lt;source lang = &amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
ThreadGroup tg = new ThreadGroup(&amp;quot;NameThreadGroup&amp;quot;);&lt;br /&gt;
Thread thread = new Thread(tg, new SecondThread(), &amp;quot;ThreadName&amp;quot;);&lt;br /&gt;
Thread thread1 = new Thread(tg, new SecondThread(), &amp;quot;ThreadName2&amp;quot;);&lt;br /&gt;
Thread thread2 = new Thread(tg, new SecondThread(), &amp;quot;ThreadName3&amp;quot;);&lt;br /&gt;
System.out.println(&amp;quot;active thread in group &amp;quot; + tg.activeCount());&lt;br /&gt;
thread.start();&lt;br /&gt;
thread1.start();&lt;br /&gt;
System.out.println(&amp;quot;active thread in group &amp;quot; + tg.activeCount());&lt;br /&gt;
Thread[] threads = new Thread[tg.activeCount()];&lt;br /&gt;
int m = tg.enumerate(threads);&lt;br /&gt;
System.out.println(&amp;quot;taked threads from group : &amp;quot; + m);&lt;br /&gt;
for (int i = 0; i &amp;lt; threads.length; i++) {&lt;br /&gt;
  System.out.println(threads[i].getName());&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
В представленном выше примере в экземпляр класса ThreadGroup помещаются три потока, два из которых запускаются на выполнение.&lt;br /&gt;
Количество активных потоков в группе определяется с помощью метода activeCount(), а в результате выполнения метода enumerate() формируется перечень всех активных потоков.&lt;br /&gt;
&lt;br /&gt;
=== Управление потоками ===&lt;br /&gt;
При запуске потоков следует учитывать и то, что их иногда приходится останавливать, причем как штатно, так и экстренно. Для того, чтобы&lt;br /&gt;
приостановить работу потока изнутри, допустим, в тот момент, когда закончилась доступные для обработки данные, можно использовать&lt;br /&gt;
два метода: sleep() и wait().&lt;br /&gt;
&amp;lt;source lang = &amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
public class ThirdThread extends Thread {&lt;br /&gt;
  public void run() {&lt;br /&gt;
    for (int i = 1; i &amp;lt; 110; i++) {&lt;br /&gt;
      if (i == 10) {&lt;br /&gt;
        try {&lt;br /&gt;
          sleep(10000);&lt;br /&gt;
        } &lt;br /&gt;
        catch (InterruptedException e) {&lt;br /&gt;
          System.out.println(&amp;quot;the thread was awaken there (just a moment ago)&amp;quot;);&lt;br /&gt;
        }&lt;br /&gt;
      }&lt;br /&gt;
      if (i == 100) {&lt;br /&gt;
        try {&lt;br /&gt;
          synchronized (this) { wait();}&lt;br /&gt;
        }&lt;br /&gt;
        catch (InterruptedException e) {&lt;br /&gt;
          System.out.println(&amp;quot;the thread was awaken there (just a moment ago)again&amp;quot;);&lt;br /&gt;
        }&lt;br /&gt;
      } &lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Методу sleep() передается переменная типа long, соответствующая количеству миллисекунд, в течении которых поток будет «спать». В&lt;br /&gt;
случае wait() поток ждет пробуждения снаружи. Применение методов sleep() и wait() требует обработки исключительной ситуации, которая возникают при пробуждении потока. В представленном ниже классе ConsoleToThreadThree потоки пробуждаются с помощью метода interrupt():&lt;br /&gt;
&amp;lt;source lang = &amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
public class ConsoleToThreadThree {&lt;br /&gt;
  public static void main(String[] args) {&lt;br /&gt;
    ThirdThread thread = new ThirdThread();&lt;br /&gt;
    thread.start();&lt;br /&gt;
    for (int i = 1; i &amp;lt; 20; i++) {&lt;br /&gt;
      System.out.println(&amp;quot;It is in main &amp;quot; + i);&lt;br /&gt;
    }&lt;br /&gt;
    thread.interrupt();&lt;br /&gt;
    for (int i = 1; i &amp;lt; 20; i++) {&lt;br /&gt;
      System.out.println(&amp;quot;It is in main &amp;quot; + i);&lt;br /&gt;
    }&lt;br /&gt;
    thread.interrupt();&lt;br /&gt;
    try {&lt;br /&gt;
      thread.join();&lt;br /&gt;
    } &lt;br /&gt;
    catch (InterruptedException ex) {&lt;br /&gt;
      System.out.println(&amp;quot;Exception in stop thread&amp;quot;);&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Отметим, что вызов метода wait() без блока синхронизации (synchronized), о котором мы поговорим чуть ниже, приводит к исключению IllegalMonitorStateException. Возникшая ошибка свидетельствует об отсутствии монитора у объекта (понятие монитора и синхронизация&lt;br /&gt;
тесно связаны, о чем мы тоже поговорим ниже). Если для приостановления потока был применен метод wait(), то для «пробуждения» потока&lt;br /&gt;
можно воспользоваться методом notify() или notifyAll(). Первый пробуждает один случайно выбранный спящий поток, а второй пытается&lt;br /&gt;
пробудить их всех.&lt;br /&gt;
&lt;br /&gt;
Кроме рассмотренных выше методов, иногда бывает целесообразно использовать метод yield(), который приостанавливает работу текущего потока. Метод yield() не переводит поток в режим ожидания, как wait(), но предоставляет другим потокам возможность начать работать&lt;br /&gt;
раньше, чем допустила бы Java-машина [фактически, поток, вызвавший yield() добровольно отдает свой квант процессорного времени, –&lt;br /&gt;
прим. ред.]. Метод yield() статичный, так что прекратить с его помощью работу другого потока не получится.&lt;br /&gt;
&lt;br /&gt;
Методов остановки потоков тоже нет (ранее присутствовали методы stop(), resume(), suspend(), но сейчас они объявлены как «deprecated» –&lt;br /&gt;
то есть нерекомендованными к использованию). На сегодня в Java принят уведомительный стиль остановки потока с помощью пары методов:&lt;br /&gt;
уже известного нам interrupt(), применяемого снаружи, чтобы выставить флаг завершения и метода isInterrupted(), вызываемого изнутри&lt;br /&gt;
потока, чтобы узнать состояние флага, свидетельствующего о том, что «пора закругляться».&lt;br /&gt;
&lt;br /&gt;
=== Мониторы и синхронизация ===&lt;br /&gt;
Что такое «монитор», о котором говорилось выше? Нет, это не дисплей, это – объект, используемый как защелка, то есть в данный момент&lt;br /&gt;
времени владеть монитором может только один поток. В случае, если поток завладел монитором, говорят, что он «вошел» в монитор, а все&lt;br /&gt;
остальные потоки, пытающиеся это сделать, будут заморожены (часто говорят, что они «ждут» монитора) до тех пор, пока владелец монитора&lt;br /&gt;
его не освободит, то есть не покинет.&lt;br /&gt;
&lt;br /&gt;
Если перейти к реалиям Java, то объектов типа монитор в явном виде просто нет! С каждым объектом связан неявный монитор, и чтобы&lt;br /&gt;
завладеть им, необходимо вызвать метод или блок, помеченный ключевым словом synchronized. Как только поток входит в такой блок, он&lt;br /&gt;
завладевает монитором объекта, переданного synchronized в качестве параметра. Так происходит и в классе ThirdThread, однако, в момент&lt;br /&gt;
вызова метода wait(), монитор отпускается. Пример synchronized-метода представлен ниже:&lt;br /&gt;
&amp;lt;source lang = &amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
public synchronized boolean sameCheck() {&lt;br /&gt;
  if (a) {&lt;br /&gt;
    a = false; return true;&lt;br /&gt;
  } &lt;br /&gt;
  else {&lt;br /&gt;
    a = true; &lt;br /&gt;
    return false;&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
В целом, синхронизация – это механизм, обеспечивающий монопольный доступ участка кода к некоторому объекту. Одним из первых&lt;br /&gt;
способов, предложенных для синхронизации работы потоков, были семафоры, концепцию которых описал Дейкстра [Dijkstra] в 1965 году&lt;br /&gt;
(часто говорят, что семафор – это классический синхронизированный примитив). Семафор используется для предоставления доступа к огра-&lt;br /&gt;
ниченному количеству ресурсов. Как правило, у семафора есть две операции: P – занять ресурс и V – освободить ресурс. Он может быть&lt;br /&gt;
реализован следующим образом:&lt;br /&gt;
&amp;lt;source lang = &amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
public class SimpleSemaphore {&lt;br /&gt;
  int counter;&lt;br /&gt;
  public SimpleSemaphore() {&lt;br /&gt;
    this.counter = 1;&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  public synchronized void p() throws InterruptedException {&lt;br /&gt;
    while (counter == 0) {&lt;br /&gt;
      wait();&lt;br /&gt;
    }&lt;br /&gt;
    counter = counter + 1;&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  public synchronized void v() throws InterruptedException {&lt;br /&gt;
    counter = counter - 1;&lt;br /&gt;
    notify();&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
Можно, конечно, реализовывать семафоры самостоятельно, но проще воспользоваться специальной библиотекой java.util.concurrent.&lt;br /&gt;
Кроме семафоров, она включает в себя еще много чего интересного. &lt;br /&gt;
&lt;br /&gt;
Отметим, что программа, в принципе, может не использовать ни один из методов синхронизации, обходясь методами wait() и notify().&lt;br /&gt;
&lt;br /&gt;
=== Взаимные блокировки ===&lt;br /&gt;
=== Литература ===&lt;br /&gt;
*1. П. Кью «Использование UNIX», ISBN 5-8275-0019-4&lt;br /&gt;
*2. В.Г. Олифер, Н.А. Олифер «Сетевые операционные системы», ISBN 5-272-00120-6&lt;br /&gt;
*3. Д. Бэкон, Т. Харрис «Операционные системы», ISBN 5-94723-969-8&lt;br /&gt;
*4. М. Фаулер «Архитектура корпоративных программных приложений», ISBN 5-8459-0579-6&lt;/div&gt;</summary>
		<author><name>Skryabin yuri</name></author>	</entry>

	<entry>
		<id>http://wiki.linuxformat.ru/wiki/LXF87-88:Java</id>
		<title>LXF87-88:Java</title>
		<link rel="alternate" type="text/html" href="http://wiki.linuxformat.ru/wiki/LXF87-88:Java"/>
				<updated>2008-03-17T11:19:49Z</updated>
		
		<summary type="html">&lt;p&gt;Skryabin yuri: /* Управление потоками */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=== Потоки в Java ===&lt;br /&gt;
''ЧАСТЬ 4: Завершая курс молодого Java-бойца, '''Антон Черноусов''' научит вас управлять потоками... Жаль, что не денежными.''&lt;br /&gt;
&lt;br /&gt;
C каждым днем появляются все более мощные процессоры, многоядерная архитектура которых стала основной темой ушедшего года, поэтому двухядерный процессор в ноутбуке уже никого не удивляет. С одной стороны – это обстоятельство приближает возможности простого пользователя к возможностям «понастоящему» больших систем. С другой (и рекламные буклеты об этом обычно молчат) – для того, чтобы использовать весь потенциал современных компьютеров, приложение должно «уметь» просчитать задачу фактически на двух или более процессорах. &lt;br /&gt;
&lt;br /&gt;
Создание эффективных алгоритмов для работы на многопроцессорных станциях – это большая и сложная работа. Несмотря на это, для любого программиста актуальна задача организации взаимодействия с медленными ресурсами (например, чтения, записи или копирования файлов, работы с принтером, сетью), так как немногие пользователи смирятся с тем, что их любимая программа «замирает» в момент выполнения какой-либо операции.&lt;br /&gt;
&lt;br /&gt;
Во избежание описанных проблем программа должна использовать потоки или процессы. Под процессом понимается заявка на потребле-&lt;br /&gt;
ние всех видов ресурсов системы, кроме одного – процессорного времени, или иначе говоря, процесс – это запущенная на выполнение программа (такое определение дается в [[LXF87/88:Java#Литература|[1]]]). Поток рассматривается как самостоятельная активность внутри процесса, хотя существуют другие трактовки этого понятия, которые зависят от используемой операционной системы (см., например, [[LXF87/88:Java#Литература|[2]]]). Поток получил свое название по аналогии с потоком команд, поступающих в процессор; при выполнении потоки делят адресное пространство и выделенную память внутри одного процесса. Процессорное время распределяется между различными потоками операционной системой, точнее, одним из компонентов ее ядра – планировщиком. Более полно с понятием процессов и потоков и механизмов работы с ними с точки зрения операционной системы вы можете ознакомиться в книге [[LXF87/88:Java#Литература|[3]]]. &lt;br /&gt;
&lt;br /&gt;
Давайте завершим наш экскурс в теорию и окунемся в реальность Java. Под процессом здесь принято понимать всеобъемлющий контекст выполнения, обеспечивающий высокий уровень изоляции охватываемых им данных от внешнего мира, а под потоком – более «легковесный» активный агент; в контексте одного процесса может функционировать целое множество потоков [[LXF87/88:Java#Литература|[4]]]. Планирование потоков в Java обеспечивается внутренними механизмами JVM.&lt;br /&gt;
&lt;br /&gt;
=== Поток, он же thread ===&lt;br /&gt;
В Java существует два способа работы с потоками: первый заключается в реализации интерфейса Runnable, второй связан с наследованием&lt;br /&gt;
класса Thread, который уже реализует данный интерфейс. В обоих случаях класс должен предоставлять реализацию метода run(). Ниже&lt;br /&gt;
приведен пример класса, реализующего поток через наследование класса Thread:&lt;br /&gt;
&amp;lt;source lang = &amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
public class FirstThread extends Thread {&lt;br /&gt;
  public void run(){&lt;br /&gt;
    for (int i = 1 ; i &amp;lt; 30; i++)&lt;br /&gt;
      System.out.println(&amp;quot;It is in thread &amp;quot;+ i);&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Собственно, метод run() и должен содержать некоторый набор инструкций (разумеется, на языке Java), которые вы хотите выполнить&lt;br /&gt;
в отдельном потоке. Например, если вы реализуете функцию копирования файла (а пользователь, скажем, копирует ISO-образ объемом&lt;br /&gt;
600 Мб), желательно, чтобы эта операция выполнялась в отдельном потоке, запуск которого можно производить следующим образом:&lt;br /&gt;
&amp;lt;source lang = &amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
public class ConsoleToThread {&lt;br /&gt;
  public static void main(String[] args) {&lt;br /&gt;
    FirstThread thread = new FirstThread();&lt;br /&gt;
    thread.start();&lt;br /&gt;
    for (int i = 1; i &amp;lt; 20; i++) {&lt;br /&gt;
      System.out.println(&amp;quot;It is in main &amp;quot; + i);&lt;br /&gt;
    }&lt;br /&gt;
    try {&lt;br /&gt;
      thread.join();&lt;br /&gt;
    } &lt;br /&gt;
    catch (InterruptedException ex) {&lt;br /&gt;
      System.out.println(&amp;quot;Exception in stop thread&amp;quot;);&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
При выполнении метода main() класса ConsoleToThread создается объект-поток FirstThread, который запускается на выполнение методом start() [заметьте – метод run() никогда не вызывается явно, – прим.ред.]. Метод join() используется в случае, когда необходимо «дождаться» завершения потока. Завершение работы потока происходит при выходе из метода run(), как явном (например, посредством return), так и неявном (если внутри метода возникло и не было обработано какое-то исключение).&lt;br /&gt;
&lt;br /&gt;
Имейте в виду (это важно!): повторный запуск уже отработавшего потока приведет к исключению IllegalThreadStateException.&lt;br /&gt;
&lt;br /&gt;
=== Реализация потока через Runnable ===&lt;br /&gt;
Давайте теперь рассмотрим пример работы с потоками через интерфейс Runnable. Если, допустим, класс SameRunnable реализует интерфейс Runnable, то запустить поток на основе этого класса на выполнение можно следующим образом:&lt;br /&gt;
&amp;lt;source lang = &amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
Runnable run = new SameRunnable();&lt;br /&gt;
Thread thread = new Thread(run);&lt;br /&gt;
thread.start();&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
В следующем примере в методе main() класса ConsoleToThreadTwo создается массив threadArray, состоящий из объектов-потоков. При&lt;br /&gt;
этом используется конструктор класса Thread, принимающий два параметра: ссылку на объект, реализующий интерфейс Runnable и&lt;br /&gt;
имя потока:&lt;br /&gt;
&amp;lt;source lang = &amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
Thread thread = new Thread(Runnable, ThreadName);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Метод getName() объекта, реализующего поток, возвращает указанное при создании имя. Обратите внимание, что в нем используется&lt;br /&gt;
статический метод Thread.currentThread(), возвращающий ссылку на объект Thread, соответствующий выполняющемуся в текущий момент&lt;br /&gt;
потоку:&lt;br /&gt;
&amp;lt;source lang = &amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
public class SecondThread implements Runnable {&lt;br /&gt;
  public String getName() {&lt;br /&gt;
    return Thread.currentThread().getName();&lt;br /&gt;
  }&lt;br /&gt;
  public void run() {&lt;br /&gt;
    for (int i = 1; i &amp;lt; 100000; i++) {&lt;br /&gt;
      if ((i % 10000) == 0) {&lt;br /&gt;
        System.out.println(getName() + &amp;quot; counts &amp;quot; + i / 10000);&lt;br /&gt;
      }&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
public class ConsoleToThreadTwo {&lt;br /&gt;
  public static void main(String[] args) {&lt;br /&gt;
    Thread[] threadArray = new Thread[3];&lt;br /&gt;
      for (int i=0; i&amp;lt;threadArray.length; i++){&lt;br /&gt;
        threadArray[i] = new Thread(new SecondThread(), &amp;quot;Thread &amp;quot; + i);&lt;br /&gt;
      }&lt;br /&gt;
      for (int i=0; i&amp;lt;threadArray.length; i++){&lt;br /&gt;
        threadArray[i].start();&lt;br /&gt;
        System.out.println(threadArray[i].getName() + &amp;quot; started&amp;quot;);&lt;br /&gt;
      }&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Проследив за выводом этой программы, можно заметить, что процессорное время распределяется между потоками практически равномерно, однако порядок их выполнения во многом случаен.&lt;br /&gt;
&lt;br /&gt;
=== Приоритеты потоков ===&lt;br /&gt;
Для управления величиной процессорного времени, выделяемого потоку, можно воспользоваться приоритетами. Установка приоритетов происходит с помощью метода Thread.setPriority(), узнать текущий приоритет позволяет метод getPriority(). В классе Thread определены&lt;br /&gt;
три константы:&lt;br /&gt;
&amp;lt;source lang = &amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
MIN_PRIORITY = 1&lt;br /&gt;
NORM_PRIORITY = 5&lt;br /&gt;
MAX_PRIORITY = 10&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Важно понимать, что значение приоритета потока предназначено для Java-машины и не соответствует реальным приоритетам потоков&lt;br /&gt;
в операционной системе.&lt;br /&gt;
&lt;br /&gt;
Давайте немного изменим код метода main() класса ConsoleToThreadTwo:&lt;br /&gt;
&amp;lt;source lang = &amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
public static void main(String[] args) {&lt;br /&gt;
  Thread[] threadArray = new Thread[3];&lt;br /&gt;
  int pr = 0;&lt;br /&gt;
  for (int i=0; i&amp;lt;threadArray.length; i++){&lt;br /&gt;
    threadArray[i] = new Thread(new SecondThread(), &amp;quot;Thread &amp;quot; + i);&lt;br /&gt;
    if (pr == 10) &lt;br /&gt;
      pr = 0; &lt;br /&gt;
    threadArray[i].setPriority(Thread.MIN_PRIORITY + pr);&lt;br /&gt;
    pr++;&lt;br /&gt;
  }&lt;br /&gt;
  for (int i=0; i&amp;lt;threadArray.length; i++){&lt;br /&gt;
    threadArray[i].start();&lt;br /&gt;
    System.out.println(threadArray[i].getName() + &amp;quot; started&amp;quot;);&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Анализ результатов работы класса показывает, что потоки, получившие более высокий приоритет, выполняются чаще. Также, благодаря&lt;br /&gt;
условию на значение переменной pr, setPriority() никогда не будет передан приоритет, превышающий 10 (MAX_PRIORITY). Если бы это про-&lt;br /&gt;
изошло, система выбросила бы исключение IllegalArgumentException.&lt;br /&gt;
&lt;br /&gt;
=== Потоки-демоны ===&lt;br /&gt;
Сделаем еще одно важное замечание: программа будет выполняться до тех пор, пока выполняется хотя бы один запущенный в ней поток;&lt;br /&gt;
единственным исключением являются потоки-демоны.&lt;br /&gt;
&lt;br /&gt;
Что же это такое? Демон отличается от «простого смертного» потока вызовом метода setDeamon(true), который необходимо сделать до&lt;br /&gt;
начала работы. Например, так:&lt;br /&gt;
&amp;lt;source lang = &amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
FirstThread thread = new FirstThread();&lt;br /&gt;
thread.setDeamon(true);&lt;br /&gt;
thread.start();&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Узнать, является ли поток демоном, можно с помощью метода isDeamon(). Обычно потоки-демоны создаются для обслуживания&lt;br /&gt;
некритичных задач, так как при завершении работы программа не дожидается их остановки, а прерывает их самостоятельно.&lt;br /&gt;
&lt;br /&gt;
=== Где искать потоки? ===&lt;br /&gt;
В большинстве случаев бывает необходимо отслеживать ранее запущенные на выполнение потоки. Использование массива потоков,&lt;br /&gt;
как в предыдущем примере, не всегда оправданно. Для хранения и обработки потоков в Java существует класс ThreadGroup. Группа,&lt;br /&gt;
к которой принадлежит создаваемый поток, опять-таки передается конструктору Thread():&lt;br /&gt;
&amp;lt;source lang = &amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
ThreadGroup tg = new ThreadGroup(&amp;quot;NameThreadGroup&amp;quot;);&lt;br /&gt;
Thread thread = new Thread(tg, new SecondThread(), &amp;quot;ThreadName&amp;quot;);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Если группа не указана явно, поток будет помещен в тот же ThreadGroup, что и его родитель.&lt;br /&gt;
&amp;lt;source lang = &amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
ThreadGroup tg = new ThreadGroup(&amp;quot;NameThreadGroup&amp;quot;);&lt;br /&gt;
Thread thread = new Thread(tg, new SecondThread(), &amp;quot;ThreadName&amp;quot;);&lt;br /&gt;
Thread thread1 = new Thread(tg, new SecondThread(), &amp;quot;ThreadName2&amp;quot;);&lt;br /&gt;
Thread thread2 = new Thread(tg, new SecondThread(), &amp;quot;ThreadName3&amp;quot;);&lt;br /&gt;
System.out.println(&amp;quot;active thread in group &amp;quot; + tg.activeCount());&lt;br /&gt;
thread.start();&lt;br /&gt;
thread1.start();&lt;br /&gt;
System.out.println(&amp;quot;active thread in group &amp;quot; + tg.activeCount());&lt;br /&gt;
Thread[] threads = new Thread[tg.activeCount()];&lt;br /&gt;
int m = tg.enumerate(threads);&lt;br /&gt;
System.out.println(&amp;quot;taked threads from group : &amp;quot; + m);&lt;br /&gt;
for (int i = 0; i &amp;lt; threads.length; i++) {&lt;br /&gt;
  System.out.println(threads[i].getName());&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
В представленном выше примере в экземпляр класса ThreadGroup помещаются три потока, два из которых запускаются на выполнение.&lt;br /&gt;
Количество активных потоков в группе определяется с помощью метода activeCount(), а в результате выполнения метода enumerate() формируется перечень всех активных потоков.&lt;br /&gt;
&lt;br /&gt;
=== Управление потоками ===&lt;br /&gt;
При запуске потоков следует учитывать и то, что их иногда приходится останавливать, причем как штатно, так и экстренно. Для того, чтобы&lt;br /&gt;
приостановить работу потока изнутри, допустим, в тот момент, когда закончилась доступные для обработки данные, можно использовать&lt;br /&gt;
два метода: sleep() и wait().&lt;br /&gt;
&amp;lt;source lang = &amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
public class ThirdThread extends Thread {&lt;br /&gt;
  public void run() {&lt;br /&gt;
    for (int i = 1; i &amp;lt; 110; i++) {&lt;br /&gt;
      if (i == 10) {&lt;br /&gt;
        try {&lt;br /&gt;
          sleep(10000);&lt;br /&gt;
        } &lt;br /&gt;
        catch (InterruptedException e) {&lt;br /&gt;
          System.out.println(&amp;quot;the thread was awaken there (just a moment ago)&amp;quot;);&lt;br /&gt;
        }&lt;br /&gt;
      }&lt;br /&gt;
      if (i == 100) {&lt;br /&gt;
        try {&lt;br /&gt;
          synchronized (this) { wait();}&lt;br /&gt;
        }&lt;br /&gt;
        catch (InterruptedException e) {&lt;br /&gt;
          System.out.println(&amp;quot;the thread was awaken there (just a moment ago)again&amp;quot;);&lt;br /&gt;
        }&lt;br /&gt;
      } &lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Методу sleep() передается переменная типа long, соответствующая количеству миллисекунд, в течении которых поток будет «спать». В&lt;br /&gt;
случае wait() поток ждет пробуждения снаружи. Применение методов sleep() и wait() требует обработки исключительной ситуации, которая возникают при пробуждении потока. В представленном ниже классе ConsoleToThreadThree потоки пробуждаются с помощью метода interrupt():&lt;br /&gt;
&amp;lt;source lang = &amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
public class ConsoleToThreadThree {&lt;br /&gt;
  public static void main(String[] args) {&lt;br /&gt;
    ThirdThread thread = new ThirdThread();&lt;br /&gt;
    thread.start();&lt;br /&gt;
    for (int i = 1; i &amp;lt; 20; i++) {&lt;br /&gt;
      System.out.println(&amp;quot;It is in main &amp;quot; + i);&lt;br /&gt;
    }&lt;br /&gt;
    thread.interrupt();&lt;br /&gt;
    for (int i = 1; i &amp;lt; 20; i++) {&lt;br /&gt;
      System.out.println(&amp;quot;It is in main &amp;quot; + i);&lt;br /&gt;
    }&lt;br /&gt;
    thread.interrupt();&lt;br /&gt;
    try {&lt;br /&gt;
      thread.join();&lt;br /&gt;
    } &lt;br /&gt;
    catch (InterruptedException ex) {&lt;br /&gt;
      System.out.println(&amp;quot;Exception in stop thread&amp;quot;);&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Отметим, что вызов метода wait() без блока синхронизации (synchronized), о котором мы поговорим чуть ниже, приводит к исключению IllegalMonitorStateException. Возникшая ошибка свидетельствует об отсутствии монитора у объекта (понятие монитора и синхронизация&lt;br /&gt;
тесно связаны, о чем мы тоже поговорим ниже). Если для приостановления потока был применен метод wait(), то для «пробуждения» потока&lt;br /&gt;
можно воспользоваться методом notify() или notifyAll(). Первый пробуждает один случайно выбранный спящий поток, а второй пытается&lt;br /&gt;
пробудить их всех.&lt;br /&gt;
&lt;br /&gt;
Кроме рассмотренных выше методов, иногда бывает целесообразно использовать метод yield(), который приостанавливает работу текущего потока. Метод yield() не переводит поток в режим ожидания, как wait(), но предоставляет другим потокам возможность начать работать&lt;br /&gt;
раньше, чем допустила бы Java-машина [фактически, поток, вызвавший yield() добровольно отдает свой квант процессорного времени, –&lt;br /&gt;
прим. ред.]. Метод yield() статичный, так что прекратить с его помощью работу другого потока не получится.&lt;br /&gt;
&lt;br /&gt;
Методов остановки потоков тоже нет (ранее присутствовали методы stop(), resume(), suspend(), но сейчас они объявлены как «deprecated» –&lt;br /&gt;
то есть нерекомендованными к использованию). На сегодня в Java принят уведомительный стиль остановки потока с помощью пары методов:&lt;br /&gt;
уже известного нам interrupt(), применяемого снаружи, чтобы выставить флаг завершения и метода isInterrupted(), вызываемого изнутри&lt;br /&gt;
потока, чтобы узнать состояние флага, свидетельствующего о том, что «пора закругляться».&lt;br /&gt;
&lt;br /&gt;
=== Мониторы и синхронизация ===&lt;br /&gt;
=== Взаимные блокировки ===&lt;br /&gt;
=== Литература ===&lt;br /&gt;
*1. П. Кью «Использование UNIX», ISBN 5-8275-0019-4&lt;br /&gt;
*2. В.Г. Олифер, Н.А. Олифер «Сетевые операционные системы», ISBN 5-272-00120-6&lt;br /&gt;
*3. Д. Бэкон, Т. Харрис «Операционные системы», ISBN 5-94723-969-8&lt;br /&gt;
*4. М. Фаулер «Архитектура корпоративных программных приложений», ISBN 5-8459-0579-6&lt;/div&gt;</summary>
		<author><name>Skryabin yuri</name></author>	</entry>

	<entry>
		<id>http://wiki.linuxformat.ru/wiki/LXF87-88:Java</id>
		<title>LXF87-88:Java</title>
		<link rel="alternate" type="text/html" href="http://wiki.linuxformat.ru/wiki/LXF87-88:Java"/>
				<updated>2008-03-17T11:10:22Z</updated>
		
		<summary type="html">&lt;p&gt;Skryabin yuri: /* Где искать потоки? */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=== Потоки в Java ===&lt;br /&gt;
''ЧАСТЬ 4: Завершая курс молодого Java-бойца, '''Антон Черноусов''' научит вас управлять потоками... Жаль, что не денежными.''&lt;br /&gt;
&lt;br /&gt;
C каждым днем появляются все более мощные процессоры, многоядерная архитектура которых стала основной темой ушедшего года, поэтому двухядерный процессор в ноутбуке уже никого не удивляет. С одной стороны – это обстоятельство приближает возможности простого пользователя к возможностям «понастоящему» больших систем. С другой (и рекламные буклеты об этом обычно молчат) – для того, чтобы использовать весь потенциал современных компьютеров, приложение должно «уметь» просчитать задачу фактически на двух или более процессорах. &lt;br /&gt;
&lt;br /&gt;
Создание эффективных алгоритмов для работы на многопроцессорных станциях – это большая и сложная работа. Несмотря на это, для любого программиста актуальна задача организации взаимодействия с медленными ресурсами (например, чтения, записи или копирования файлов, работы с принтером, сетью), так как немногие пользователи смирятся с тем, что их любимая программа «замирает» в момент выполнения какой-либо операции.&lt;br /&gt;
&lt;br /&gt;
Во избежание описанных проблем программа должна использовать потоки или процессы. Под процессом понимается заявка на потребле-&lt;br /&gt;
ние всех видов ресурсов системы, кроме одного – процессорного времени, или иначе говоря, процесс – это запущенная на выполнение программа (такое определение дается в [[LXF87/88:Java#Литература|[1]]]). Поток рассматривается как самостоятельная активность внутри процесса, хотя существуют другие трактовки этого понятия, которые зависят от используемой операционной системы (см., например, [[LXF87/88:Java#Литература|[2]]]). Поток получил свое название по аналогии с потоком команд, поступающих в процессор; при выполнении потоки делят адресное пространство и выделенную память внутри одного процесса. Процессорное время распределяется между различными потоками операционной системой, точнее, одним из компонентов ее ядра – планировщиком. Более полно с понятием процессов и потоков и механизмов работы с ними с точки зрения операционной системы вы можете ознакомиться в книге [[LXF87/88:Java#Литература|[3]]]. &lt;br /&gt;
&lt;br /&gt;
Давайте завершим наш экскурс в теорию и окунемся в реальность Java. Под процессом здесь принято понимать всеобъемлющий контекст выполнения, обеспечивающий высокий уровень изоляции охватываемых им данных от внешнего мира, а под потоком – более «легковесный» активный агент; в контексте одного процесса может функционировать целое множество потоков [[LXF87/88:Java#Литература|[4]]]. Планирование потоков в Java обеспечивается внутренними механизмами JVM.&lt;br /&gt;
&lt;br /&gt;
=== Поток, он же thread ===&lt;br /&gt;
В Java существует два способа работы с потоками: первый заключается в реализации интерфейса Runnable, второй связан с наследованием&lt;br /&gt;
класса Thread, который уже реализует данный интерфейс. В обоих случаях класс должен предоставлять реализацию метода run(). Ниже&lt;br /&gt;
приведен пример класса, реализующего поток через наследование класса Thread:&lt;br /&gt;
&amp;lt;source lang = &amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
public class FirstThread extends Thread {&lt;br /&gt;
  public void run(){&lt;br /&gt;
    for (int i = 1 ; i &amp;lt; 30; i++)&lt;br /&gt;
      System.out.println(&amp;quot;It is in thread &amp;quot;+ i);&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Собственно, метод run() и должен содержать некоторый набор инструкций (разумеется, на языке Java), которые вы хотите выполнить&lt;br /&gt;
в отдельном потоке. Например, если вы реализуете функцию копирования файла (а пользователь, скажем, копирует ISO-образ объемом&lt;br /&gt;
600 Мб), желательно, чтобы эта операция выполнялась в отдельном потоке, запуск которого можно производить следующим образом:&lt;br /&gt;
&amp;lt;source lang = &amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
public class ConsoleToThread {&lt;br /&gt;
  public static void main(String[] args) {&lt;br /&gt;
    FirstThread thread = new FirstThread();&lt;br /&gt;
    thread.start();&lt;br /&gt;
    for (int i = 1; i &amp;lt; 20; i++) {&lt;br /&gt;
      System.out.println(&amp;quot;It is in main &amp;quot; + i);&lt;br /&gt;
    }&lt;br /&gt;
    try {&lt;br /&gt;
      thread.join();&lt;br /&gt;
    } &lt;br /&gt;
    catch (InterruptedException ex) {&lt;br /&gt;
      System.out.println(&amp;quot;Exception in stop thread&amp;quot;);&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
При выполнении метода main() класса ConsoleToThread создается объект-поток FirstThread, который запускается на выполнение методом start() [заметьте – метод run() никогда не вызывается явно, – прим.ред.]. Метод join() используется в случае, когда необходимо «дождаться» завершения потока. Завершение работы потока происходит при выходе из метода run(), как явном (например, посредством return), так и неявном (если внутри метода возникло и не было обработано какое-то исключение).&lt;br /&gt;
&lt;br /&gt;
Имейте в виду (это важно!): повторный запуск уже отработавшего потока приведет к исключению IllegalThreadStateException.&lt;br /&gt;
&lt;br /&gt;
=== Реализация потока через Runnable ===&lt;br /&gt;
Давайте теперь рассмотрим пример работы с потоками через интерфейс Runnable. Если, допустим, класс SameRunnable реализует интерфейс Runnable, то запустить поток на основе этого класса на выполнение можно следующим образом:&lt;br /&gt;
&amp;lt;source lang = &amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
Runnable run = new SameRunnable();&lt;br /&gt;
Thread thread = new Thread(run);&lt;br /&gt;
thread.start();&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
В следующем примере в методе main() класса ConsoleToThreadTwo создается массив threadArray, состоящий из объектов-потоков. При&lt;br /&gt;
этом используется конструктор класса Thread, принимающий два параметра: ссылку на объект, реализующий интерфейс Runnable и&lt;br /&gt;
имя потока:&lt;br /&gt;
&amp;lt;source lang = &amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
Thread thread = new Thread(Runnable, ThreadName);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Метод getName() объекта, реализующего поток, возвращает указанное при создании имя. Обратите внимание, что в нем используется&lt;br /&gt;
статический метод Thread.currentThread(), возвращающий ссылку на объект Thread, соответствующий выполняющемуся в текущий момент&lt;br /&gt;
потоку:&lt;br /&gt;
&amp;lt;source lang = &amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
public class SecondThread implements Runnable {&lt;br /&gt;
  public String getName() {&lt;br /&gt;
    return Thread.currentThread().getName();&lt;br /&gt;
  }&lt;br /&gt;
  public void run() {&lt;br /&gt;
    for (int i = 1; i &amp;lt; 100000; i++) {&lt;br /&gt;
      if ((i % 10000) == 0) {&lt;br /&gt;
        System.out.println(getName() + &amp;quot; counts &amp;quot; + i / 10000);&lt;br /&gt;
      }&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
public class ConsoleToThreadTwo {&lt;br /&gt;
  public static void main(String[] args) {&lt;br /&gt;
    Thread[] threadArray = new Thread[3];&lt;br /&gt;
      for (int i=0; i&amp;lt;threadArray.length; i++){&lt;br /&gt;
        threadArray[i] = new Thread(new SecondThread(), &amp;quot;Thread &amp;quot; + i);&lt;br /&gt;
      }&lt;br /&gt;
      for (int i=0; i&amp;lt;threadArray.length; i++){&lt;br /&gt;
        threadArray[i].start();&lt;br /&gt;
        System.out.println(threadArray[i].getName() + &amp;quot; started&amp;quot;);&lt;br /&gt;
      }&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Проследив за выводом этой программы, можно заметить, что процессорное время распределяется между потоками практически равномерно, однако порядок их выполнения во многом случаен.&lt;br /&gt;
&lt;br /&gt;
=== Приоритеты потоков ===&lt;br /&gt;
Для управления величиной процессорного времени, выделяемого потоку, можно воспользоваться приоритетами. Установка приоритетов происходит с помощью метода Thread.setPriority(), узнать текущий приоритет позволяет метод getPriority(). В классе Thread определены&lt;br /&gt;
три константы:&lt;br /&gt;
&amp;lt;source lang = &amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
MIN_PRIORITY = 1&lt;br /&gt;
NORM_PRIORITY = 5&lt;br /&gt;
MAX_PRIORITY = 10&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Важно понимать, что значение приоритета потока предназначено для Java-машины и не соответствует реальным приоритетам потоков&lt;br /&gt;
в операционной системе.&lt;br /&gt;
&lt;br /&gt;
Давайте немного изменим код метода main() класса ConsoleToThreadTwo:&lt;br /&gt;
&amp;lt;source lang = &amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
public static void main(String[] args) {&lt;br /&gt;
  Thread[] threadArray = new Thread[3];&lt;br /&gt;
  int pr = 0;&lt;br /&gt;
  for (int i=0; i&amp;lt;threadArray.length; i++){&lt;br /&gt;
    threadArray[i] = new Thread(new SecondThread(), &amp;quot;Thread &amp;quot; + i);&lt;br /&gt;
    if (pr == 10) &lt;br /&gt;
      pr = 0; &lt;br /&gt;
    threadArray[i].setPriority(Thread.MIN_PRIORITY + pr);&lt;br /&gt;
    pr++;&lt;br /&gt;
  }&lt;br /&gt;
  for (int i=0; i&amp;lt;threadArray.length; i++){&lt;br /&gt;
    threadArray[i].start();&lt;br /&gt;
    System.out.println(threadArray[i].getName() + &amp;quot; started&amp;quot;);&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Анализ результатов работы класса показывает, что потоки, получившие более высокий приоритет, выполняются чаще. Также, благодаря&lt;br /&gt;
условию на значение переменной pr, setPriority() никогда не будет передан приоритет, превышающий 10 (MAX_PRIORITY). Если бы это про-&lt;br /&gt;
изошло, система выбросила бы исключение IllegalArgumentException.&lt;br /&gt;
&lt;br /&gt;
=== Потоки-демоны ===&lt;br /&gt;
Сделаем еще одно важное замечание: программа будет выполняться до тех пор, пока выполняется хотя бы один запущенный в ней поток;&lt;br /&gt;
единственным исключением являются потоки-демоны.&lt;br /&gt;
&lt;br /&gt;
Что же это такое? Демон отличается от «простого смертного» потока вызовом метода setDeamon(true), который необходимо сделать до&lt;br /&gt;
начала работы. Например, так:&lt;br /&gt;
&amp;lt;source lang = &amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
FirstThread thread = new FirstThread();&lt;br /&gt;
thread.setDeamon(true);&lt;br /&gt;
thread.start();&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Узнать, является ли поток демоном, можно с помощью метода isDeamon(). Обычно потоки-демоны создаются для обслуживания&lt;br /&gt;
некритичных задач, так как при завершении работы программа не дожидается их остановки, а прерывает их самостоятельно.&lt;br /&gt;
&lt;br /&gt;
=== Где искать потоки? ===&lt;br /&gt;
В большинстве случаев бывает необходимо отслеживать ранее запущенные на выполнение потоки. Использование массива потоков,&lt;br /&gt;
как в предыдущем примере, не всегда оправданно. Для хранения и обработки потоков в Java существует класс ThreadGroup. Группа,&lt;br /&gt;
к которой принадлежит создаваемый поток, опять-таки передается конструктору Thread():&lt;br /&gt;
&amp;lt;source lang = &amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
ThreadGroup tg = new ThreadGroup(&amp;quot;NameThreadGroup&amp;quot;);&lt;br /&gt;
Thread thread = new Thread(tg, new SecondThread(), &amp;quot;ThreadName&amp;quot;);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Если группа не указана явно, поток будет помещен в тот же ThreadGroup, что и его родитель.&lt;br /&gt;
&amp;lt;source lang = &amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
ThreadGroup tg = new ThreadGroup(&amp;quot;NameThreadGroup&amp;quot;);&lt;br /&gt;
Thread thread = new Thread(tg, new SecondThread(), &amp;quot;ThreadName&amp;quot;);&lt;br /&gt;
Thread thread1 = new Thread(tg, new SecondThread(), &amp;quot;ThreadName2&amp;quot;);&lt;br /&gt;
Thread thread2 = new Thread(tg, new SecondThread(), &amp;quot;ThreadName3&amp;quot;);&lt;br /&gt;
System.out.println(&amp;quot;active thread in group &amp;quot; + tg.activeCount());&lt;br /&gt;
thread.start();&lt;br /&gt;
thread1.start();&lt;br /&gt;
System.out.println(&amp;quot;active thread in group &amp;quot; + tg.activeCount());&lt;br /&gt;
Thread[] threads = new Thread[tg.activeCount()];&lt;br /&gt;
int m = tg.enumerate(threads);&lt;br /&gt;
System.out.println(&amp;quot;taked threads from group : &amp;quot; + m);&lt;br /&gt;
for (int i = 0; i &amp;lt; threads.length; i++) {&lt;br /&gt;
  System.out.println(threads[i].getName());&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
В представленном выше примере в экземпляр класса ThreadGroup помещаются три потока, два из которых запускаются на выполнение.&lt;br /&gt;
Количество активных потоков в группе определяется с помощью метода activeCount(), а в результате выполнения метода enumerate() формируется перечень всех активных потоков.&lt;br /&gt;
&lt;br /&gt;
=== Управление потоками ===&lt;br /&gt;
=== Мониторы и синхронизация ===&lt;br /&gt;
=== Взаимные блокировки ===&lt;br /&gt;
=== Литература ===&lt;br /&gt;
*1. П. Кью «Использование UNIX», ISBN 5-8275-0019-4&lt;br /&gt;
*2. В.Г. Олифер, Н.А. Олифер «Сетевые операционные системы», ISBN 5-272-00120-6&lt;br /&gt;
*3. Д. Бэкон, Т. Харрис «Операционные системы», ISBN 5-94723-969-8&lt;br /&gt;
*4. М. Фаулер «Архитектура корпоративных программных приложений», ISBN 5-8459-0579-6&lt;/div&gt;</summary>
		<author><name>Skryabin yuri</name></author>	</entry>

	<entry>
		<id>http://wiki.linuxformat.ru/wiki/LXF87-88:Java</id>
		<title>LXF87-88:Java</title>
		<link rel="alternate" type="text/html" href="http://wiki.linuxformat.ru/wiki/LXF87-88:Java"/>
				<updated>2008-03-17T10:24:44Z</updated>
		
		<summary type="html">&lt;p&gt;Skryabin yuri: /* Потоки-демоны */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=== Потоки в Java ===&lt;br /&gt;
''ЧАСТЬ 4: Завершая курс молодого Java-бойца, '''Антон Черноусов''' научит вас управлять потоками... Жаль, что не денежными.''&lt;br /&gt;
&lt;br /&gt;
C каждым днем появляются все более мощные процессоры, многоядерная архитектура которых стала основной темой ушедшего года, поэтому двухядерный процессор в ноутбуке уже никого не удивляет. С одной стороны – это обстоятельство приближает возможности простого пользователя к возможностям «понастоящему» больших систем. С другой (и рекламные буклеты об этом обычно молчат) – для того, чтобы использовать весь потенциал современных компьютеров, приложение должно «уметь» просчитать задачу фактически на двух или более процессорах. &lt;br /&gt;
&lt;br /&gt;
Создание эффективных алгоритмов для работы на многопроцессорных станциях – это большая и сложная работа. Несмотря на это, для любого программиста актуальна задача организации взаимодействия с медленными ресурсами (например, чтения, записи или копирования файлов, работы с принтером, сетью), так как немногие пользователи смирятся с тем, что их любимая программа «замирает» в момент выполнения какой-либо операции.&lt;br /&gt;
&lt;br /&gt;
Во избежание описанных проблем программа должна использовать потоки или процессы. Под процессом понимается заявка на потребле-&lt;br /&gt;
ние всех видов ресурсов системы, кроме одного – процессорного времени, или иначе говоря, процесс – это запущенная на выполнение программа (такое определение дается в [[LXF87/88:Java#Литература|[1]]]). Поток рассматривается как самостоятельная активность внутри процесса, хотя существуют другие трактовки этого понятия, которые зависят от используемой операционной системы (см., например, [[LXF87/88:Java#Литература|[2]]]). Поток получил свое название по аналогии с потоком команд, поступающих в процессор; при выполнении потоки делят адресное пространство и выделенную память внутри одного процесса. Процессорное время распределяется между различными потоками операционной системой, точнее, одним из компонентов ее ядра – планировщиком. Более полно с понятием процессов и потоков и механизмов работы с ними с точки зрения операционной системы вы можете ознакомиться в книге [[LXF87/88:Java#Литература|[3]]]. &lt;br /&gt;
&lt;br /&gt;
Давайте завершим наш экскурс в теорию и окунемся в реальность Java. Под процессом здесь принято понимать всеобъемлющий контекст выполнения, обеспечивающий высокий уровень изоляции охватываемых им данных от внешнего мира, а под потоком – более «легковесный» активный агент; в контексте одного процесса может функционировать целое множество потоков [[LXF87/88:Java#Литература|[4]]]. Планирование потоков в Java обеспечивается внутренними механизмами JVM.&lt;br /&gt;
&lt;br /&gt;
=== Поток, он же thread ===&lt;br /&gt;
В Java существует два способа работы с потоками: первый заключается в реализации интерфейса Runnable, второй связан с наследованием&lt;br /&gt;
класса Thread, который уже реализует данный интерфейс. В обоих случаях класс должен предоставлять реализацию метода run(). Ниже&lt;br /&gt;
приведен пример класса, реализующего поток через наследование класса Thread:&lt;br /&gt;
&amp;lt;source lang = &amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
public class FirstThread extends Thread {&lt;br /&gt;
  public void run(){&lt;br /&gt;
    for (int i = 1 ; i &amp;lt; 30; i++)&lt;br /&gt;
      System.out.println(&amp;quot;It is in thread &amp;quot;+ i);&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Собственно, метод run() и должен содержать некоторый набор инструкций (разумеется, на языке Java), которые вы хотите выполнить&lt;br /&gt;
в отдельном потоке. Например, если вы реализуете функцию копирования файла (а пользователь, скажем, копирует ISO-образ объемом&lt;br /&gt;
600 Мб), желательно, чтобы эта операция выполнялась в отдельном потоке, запуск которого можно производить следующим образом:&lt;br /&gt;
&amp;lt;source lang = &amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
public class ConsoleToThread {&lt;br /&gt;
  public static void main(String[] args) {&lt;br /&gt;
    FirstThread thread = new FirstThread();&lt;br /&gt;
    thread.start();&lt;br /&gt;
    for (int i = 1; i &amp;lt; 20; i++) {&lt;br /&gt;
      System.out.println(&amp;quot;It is in main &amp;quot; + i);&lt;br /&gt;
    }&lt;br /&gt;
    try {&lt;br /&gt;
      thread.join();&lt;br /&gt;
    } &lt;br /&gt;
    catch (InterruptedException ex) {&lt;br /&gt;
      System.out.println(&amp;quot;Exception in stop thread&amp;quot;);&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
При выполнении метода main() класса ConsoleToThread создается объект-поток FirstThread, который запускается на выполнение методом start() [заметьте – метод run() никогда не вызывается явно, – прим.ред.]. Метод join() используется в случае, когда необходимо «дождаться» завершения потока. Завершение работы потока происходит при выходе из метода run(), как явном (например, посредством return), так и неявном (если внутри метода возникло и не было обработано какое-то исключение).&lt;br /&gt;
&lt;br /&gt;
Имейте в виду (это важно!): повторный запуск уже отработавшего потока приведет к исключению IllegalThreadStateException.&lt;br /&gt;
&lt;br /&gt;
=== Реализация потока через Runnable ===&lt;br /&gt;
Давайте теперь рассмотрим пример работы с потоками через интерфейс Runnable. Если, допустим, класс SameRunnable реализует интерфейс Runnable, то запустить поток на основе этого класса на выполнение можно следующим образом:&lt;br /&gt;
&amp;lt;source lang = &amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
Runnable run = new SameRunnable();&lt;br /&gt;
Thread thread = new Thread(run);&lt;br /&gt;
thread.start();&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
В следующем примере в методе main() класса ConsoleToThreadTwo создается массив threadArray, состоящий из объектов-потоков. При&lt;br /&gt;
этом используется конструктор класса Thread, принимающий два параметра: ссылку на объект, реализующий интерфейс Runnable и&lt;br /&gt;
имя потока:&lt;br /&gt;
&amp;lt;source lang = &amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
Thread thread = new Thread(Runnable, ThreadName);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Метод getName() объекта, реализующего поток, возвращает указанное при создании имя. Обратите внимание, что в нем используется&lt;br /&gt;
статический метод Thread.currentThread(), возвращающий ссылку на объект Thread, соответствующий выполняющемуся в текущий момент&lt;br /&gt;
потоку:&lt;br /&gt;
&amp;lt;source lang = &amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
public class SecondThread implements Runnable {&lt;br /&gt;
  public String getName() {&lt;br /&gt;
    return Thread.currentThread().getName();&lt;br /&gt;
  }&lt;br /&gt;
  public void run() {&lt;br /&gt;
    for (int i = 1; i &amp;lt; 100000; i++) {&lt;br /&gt;
      if ((i % 10000) == 0) {&lt;br /&gt;
        System.out.println(getName() + &amp;quot; counts &amp;quot; + i / 10000);&lt;br /&gt;
      }&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
public class ConsoleToThreadTwo {&lt;br /&gt;
  public static void main(String[] args) {&lt;br /&gt;
    Thread[] threadArray = new Thread[3];&lt;br /&gt;
      for (int i=0; i&amp;lt;threadArray.length; i++){&lt;br /&gt;
        threadArray[i] = new Thread(new SecondThread(), &amp;quot;Thread &amp;quot; + i);&lt;br /&gt;
      }&lt;br /&gt;
      for (int i=0; i&amp;lt;threadArray.length; i++){&lt;br /&gt;
        threadArray[i].start();&lt;br /&gt;
        System.out.println(threadArray[i].getName() + &amp;quot; started&amp;quot;);&lt;br /&gt;
      }&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Проследив за выводом этой программы, можно заметить, что процессорное время распределяется между потоками практически равномерно, однако порядок их выполнения во многом случаен.&lt;br /&gt;
&lt;br /&gt;
=== Приоритеты потоков ===&lt;br /&gt;
Для управления величиной процессорного времени, выделяемого потоку, можно воспользоваться приоритетами. Установка приоритетов происходит с помощью метода Thread.setPriority(), узнать текущий приоритет позволяет метод getPriority(). В классе Thread определены&lt;br /&gt;
три константы:&lt;br /&gt;
&amp;lt;source lang = &amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
MIN_PRIORITY = 1&lt;br /&gt;
NORM_PRIORITY = 5&lt;br /&gt;
MAX_PRIORITY = 10&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Важно понимать, что значение приоритета потока предназначено для Java-машины и не соответствует реальным приоритетам потоков&lt;br /&gt;
в операционной системе.&lt;br /&gt;
&lt;br /&gt;
Давайте немного изменим код метода main() класса ConsoleToThreadTwo:&lt;br /&gt;
&amp;lt;source lang = &amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
public static void main(String[] args) {&lt;br /&gt;
  Thread[] threadArray = new Thread[3];&lt;br /&gt;
  int pr = 0;&lt;br /&gt;
  for (int i=0; i&amp;lt;threadArray.length; i++){&lt;br /&gt;
    threadArray[i] = new Thread(new SecondThread(), &amp;quot;Thread &amp;quot; + i);&lt;br /&gt;
    if (pr == 10) &lt;br /&gt;
      pr = 0; &lt;br /&gt;
    threadArray[i].setPriority(Thread.MIN_PRIORITY + pr);&lt;br /&gt;
    pr++;&lt;br /&gt;
  }&lt;br /&gt;
  for (int i=0; i&amp;lt;threadArray.length; i++){&lt;br /&gt;
    threadArray[i].start();&lt;br /&gt;
    System.out.println(threadArray[i].getName() + &amp;quot; started&amp;quot;);&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Анализ результатов работы класса показывает, что потоки, получившие более высокий приоритет, выполняются чаще. Также, благодаря&lt;br /&gt;
условию на значение переменной pr, setPriority() никогда не будет передан приоритет, превышающий 10 (MAX_PRIORITY). Если бы это про-&lt;br /&gt;
изошло, система выбросила бы исключение IllegalArgumentException.&lt;br /&gt;
&lt;br /&gt;
=== Потоки-демоны ===&lt;br /&gt;
Сделаем еще одно важное замечание: программа будет выполняться до тех пор, пока выполняется хотя бы один запущенный в ней поток;&lt;br /&gt;
единственным исключением являются потоки-демоны.&lt;br /&gt;
&lt;br /&gt;
Что же это такое? Демон отличается от «простого смертного» потока вызовом метода setDeamon(true), который необходимо сделать до&lt;br /&gt;
начала работы. Например, так:&lt;br /&gt;
&amp;lt;source lang = &amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
FirstThread thread = new FirstThread();&lt;br /&gt;
thread.setDeamon(true);&lt;br /&gt;
thread.start();&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Узнать, является ли поток демоном, можно с помощью метода isDeamon(). Обычно потоки-демоны создаются для обслуживания&lt;br /&gt;
некритичных задач, так как при завершении работы программа не дожидается их остановки, а прерывает их самостоятельно.&lt;br /&gt;
&lt;br /&gt;
=== Где искать потоки? ===&lt;br /&gt;
=== Управление потоками ===&lt;br /&gt;
=== Мониторы и синхронизация ===&lt;br /&gt;
=== Взаимные блокировки ===&lt;br /&gt;
=== Литература ===&lt;br /&gt;
*1. П. Кью «Использование UNIX», ISBN 5-8275-0019-4&lt;br /&gt;
*2. В.Г. Олифер, Н.А. Олифер «Сетевые операционные системы», ISBN 5-272-00120-6&lt;br /&gt;
*3. Д. Бэкон, Т. Харрис «Операционные системы», ISBN 5-94723-969-8&lt;br /&gt;
*4. М. Фаулер «Архитектура корпоративных программных приложений», ISBN 5-8459-0579-6&lt;/div&gt;</summary>
		<author><name>Skryabin yuri</name></author>	</entry>

	<entry>
		<id>http://wiki.linuxformat.ru/wiki/LXF87-88:Java</id>
		<title>LXF87-88:Java</title>
		<link rel="alternate" type="text/html" href="http://wiki.linuxformat.ru/wiki/LXF87-88:Java"/>
				<updated>2008-03-17T10:23:01Z</updated>
		
		<summary type="html">&lt;p&gt;Skryabin yuri: /* Приоритеты потоков */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=== Потоки в Java ===&lt;br /&gt;
''ЧАСТЬ 4: Завершая курс молодого Java-бойца, '''Антон Черноусов''' научит вас управлять потоками... Жаль, что не денежными.''&lt;br /&gt;
&lt;br /&gt;
C каждым днем появляются все более мощные процессоры, многоядерная архитектура которых стала основной темой ушедшего года, поэтому двухядерный процессор в ноутбуке уже никого не удивляет. С одной стороны – это обстоятельство приближает возможности простого пользователя к возможностям «понастоящему» больших систем. С другой (и рекламные буклеты об этом обычно молчат) – для того, чтобы использовать весь потенциал современных компьютеров, приложение должно «уметь» просчитать задачу фактически на двух или более процессорах. &lt;br /&gt;
&lt;br /&gt;
Создание эффективных алгоритмов для работы на многопроцессорных станциях – это большая и сложная работа. Несмотря на это, для любого программиста актуальна задача организации взаимодействия с медленными ресурсами (например, чтения, записи или копирования файлов, работы с принтером, сетью), так как немногие пользователи смирятся с тем, что их любимая программа «замирает» в момент выполнения какой-либо операции.&lt;br /&gt;
&lt;br /&gt;
Во избежание описанных проблем программа должна использовать потоки или процессы. Под процессом понимается заявка на потребле-&lt;br /&gt;
ние всех видов ресурсов системы, кроме одного – процессорного времени, или иначе говоря, процесс – это запущенная на выполнение программа (такое определение дается в [[LXF87/88:Java#Литература|[1]]]). Поток рассматривается как самостоятельная активность внутри процесса, хотя существуют другие трактовки этого понятия, которые зависят от используемой операционной системы (см., например, [[LXF87/88:Java#Литература|[2]]]). Поток получил свое название по аналогии с потоком команд, поступающих в процессор; при выполнении потоки делят адресное пространство и выделенную память внутри одного процесса. Процессорное время распределяется между различными потоками операционной системой, точнее, одним из компонентов ее ядра – планировщиком. Более полно с понятием процессов и потоков и механизмов работы с ними с точки зрения операционной системы вы можете ознакомиться в книге [[LXF87/88:Java#Литература|[3]]]. &lt;br /&gt;
&lt;br /&gt;
Давайте завершим наш экскурс в теорию и окунемся в реальность Java. Под процессом здесь принято понимать всеобъемлющий контекст выполнения, обеспечивающий высокий уровень изоляции охватываемых им данных от внешнего мира, а под потоком – более «легковесный» активный агент; в контексте одного процесса может функционировать целое множество потоков [[LXF87/88:Java#Литература|[4]]]. Планирование потоков в Java обеспечивается внутренними механизмами JVM.&lt;br /&gt;
&lt;br /&gt;
=== Поток, он же thread ===&lt;br /&gt;
В Java существует два способа работы с потоками: первый заключается в реализации интерфейса Runnable, второй связан с наследованием&lt;br /&gt;
класса Thread, который уже реализует данный интерфейс. В обоих случаях класс должен предоставлять реализацию метода run(). Ниже&lt;br /&gt;
приведен пример класса, реализующего поток через наследование класса Thread:&lt;br /&gt;
&amp;lt;source lang = &amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
public class FirstThread extends Thread {&lt;br /&gt;
  public void run(){&lt;br /&gt;
    for (int i = 1 ; i &amp;lt; 30; i++)&lt;br /&gt;
      System.out.println(&amp;quot;It is in thread &amp;quot;+ i);&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Собственно, метод run() и должен содержать некоторый набор инструкций (разумеется, на языке Java), которые вы хотите выполнить&lt;br /&gt;
в отдельном потоке. Например, если вы реализуете функцию копирования файла (а пользователь, скажем, копирует ISO-образ объемом&lt;br /&gt;
600 Мб), желательно, чтобы эта операция выполнялась в отдельном потоке, запуск которого можно производить следующим образом:&lt;br /&gt;
&amp;lt;source lang = &amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
public class ConsoleToThread {&lt;br /&gt;
  public static void main(String[] args) {&lt;br /&gt;
    FirstThread thread = new FirstThread();&lt;br /&gt;
    thread.start();&lt;br /&gt;
    for (int i = 1; i &amp;lt; 20; i++) {&lt;br /&gt;
      System.out.println(&amp;quot;It is in main &amp;quot; + i);&lt;br /&gt;
    }&lt;br /&gt;
    try {&lt;br /&gt;
      thread.join();&lt;br /&gt;
    } &lt;br /&gt;
    catch (InterruptedException ex) {&lt;br /&gt;
      System.out.println(&amp;quot;Exception in stop thread&amp;quot;);&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
При выполнении метода main() класса ConsoleToThread создается объект-поток FirstThread, который запускается на выполнение методом start() [заметьте – метод run() никогда не вызывается явно, – прим.ред.]. Метод join() используется в случае, когда необходимо «дождаться» завершения потока. Завершение работы потока происходит при выходе из метода run(), как явном (например, посредством return), так и неявном (если внутри метода возникло и не было обработано какое-то исключение).&lt;br /&gt;
&lt;br /&gt;
Имейте в виду (это важно!): повторный запуск уже отработавшего потока приведет к исключению IllegalThreadStateException.&lt;br /&gt;
&lt;br /&gt;
=== Реализация потока через Runnable ===&lt;br /&gt;
Давайте теперь рассмотрим пример работы с потоками через интерфейс Runnable. Если, допустим, класс SameRunnable реализует интерфейс Runnable, то запустить поток на основе этого класса на выполнение можно следующим образом:&lt;br /&gt;
&amp;lt;source lang = &amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
Runnable run = new SameRunnable();&lt;br /&gt;
Thread thread = new Thread(run);&lt;br /&gt;
thread.start();&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
В следующем примере в методе main() класса ConsoleToThreadTwo создается массив threadArray, состоящий из объектов-потоков. При&lt;br /&gt;
этом используется конструктор класса Thread, принимающий два параметра: ссылку на объект, реализующий интерфейс Runnable и&lt;br /&gt;
имя потока:&lt;br /&gt;
&amp;lt;source lang = &amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
Thread thread = new Thread(Runnable, ThreadName);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Метод getName() объекта, реализующего поток, возвращает указанное при создании имя. Обратите внимание, что в нем используется&lt;br /&gt;
статический метод Thread.currentThread(), возвращающий ссылку на объект Thread, соответствующий выполняющемуся в текущий момент&lt;br /&gt;
потоку:&lt;br /&gt;
&amp;lt;source lang = &amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
public class SecondThread implements Runnable {&lt;br /&gt;
  public String getName() {&lt;br /&gt;
    return Thread.currentThread().getName();&lt;br /&gt;
  }&lt;br /&gt;
  public void run() {&lt;br /&gt;
    for (int i = 1; i &amp;lt; 100000; i++) {&lt;br /&gt;
      if ((i % 10000) == 0) {&lt;br /&gt;
        System.out.println(getName() + &amp;quot; counts &amp;quot; + i / 10000);&lt;br /&gt;
      }&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
public class ConsoleToThreadTwo {&lt;br /&gt;
  public static void main(String[] args) {&lt;br /&gt;
    Thread[] threadArray = new Thread[3];&lt;br /&gt;
      for (int i=0; i&amp;lt;threadArray.length; i++){&lt;br /&gt;
        threadArray[i] = new Thread(new SecondThread(), &amp;quot;Thread &amp;quot; + i);&lt;br /&gt;
      }&lt;br /&gt;
      for (int i=0; i&amp;lt;threadArray.length; i++){&lt;br /&gt;
        threadArray[i].start();&lt;br /&gt;
        System.out.println(threadArray[i].getName() + &amp;quot; started&amp;quot;);&lt;br /&gt;
      }&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Проследив за выводом этой программы, можно заметить, что процессорное время распределяется между потоками практически равномерно, однако порядок их выполнения во многом случаен.&lt;br /&gt;
&lt;br /&gt;
=== Приоритеты потоков ===&lt;br /&gt;
Для управления величиной процессорного времени, выделяемого потоку, можно воспользоваться приоритетами. Установка приоритетов происходит с помощью метода Thread.setPriority(), узнать текущий приоритет позволяет метод getPriority(). В классе Thread определены&lt;br /&gt;
три константы:&lt;br /&gt;
&amp;lt;source lang = &amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
MIN_PRIORITY = 1&lt;br /&gt;
NORM_PRIORITY = 5&lt;br /&gt;
MAX_PRIORITY = 10&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Важно понимать, что значение приоритета потока предназначено для Java-машины и не соответствует реальным приоритетам потоков&lt;br /&gt;
в операционной системе.&lt;br /&gt;
&lt;br /&gt;
Давайте немного изменим код метода main() класса ConsoleToThreadTwo:&lt;br /&gt;
&amp;lt;source lang = &amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
public static void main(String[] args) {&lt;br /&gt;
  Thread[] threadArray = new Thread[3];&lt;br /&gt;
  int pr = 0;&lt;br /&gt;
  for (int i=0; i&amp;lt;threadArray.length; i++){&lt;br /&gt;
    threadArray[i] = new Thread(new SecondThread(), &amp;quot;Thread &amp;quot; + i);&lt;br /&gt;
    if (pr == 10) &lt;br /&gt;
      pr = 0; &lt;br /&gt;
    threadArray[i].setPriority(Thread.MIN_PRIORITY + pr);&lt;br /&gt;
    pr++;&lt;br /&gt;
  }&lt;br /&gt;
  for (int i=0; i&amp;lt;threadArray.length; i++){&lt;br /&gt;
    threadArray[i].start();&lt;br /&gt;
    System.out.println(threadArray[i].getName() + &amp;quot; started&amp;quot;);&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Анализ результатов работы класса показывает, что потоки, получившие более высокий приоритет, выполняются чаще. Также, благодаря&lt;br /&gt;
условию на значение переменной pr, setPriority() никогда не будет передан приоритет, превышающий 10 (MAX_PRIORITY). Если бы это про-&lt;br /&gt;
изошло, система выбросила бы исключение IllegalArgumentException.&lt;br /&gt;
&lt;br /&gt;
=== Потоки-демоны ===&lt;br /&gt;
=== Где искать потоки? ===&lt;br /&gt;
=== Управление потоками ===&lt;br /&gt;
=== Мониторы и синхронизация ===&lt;br /&gt;
=== Взаимные блокировки ===&lt;br /&gt;
=== Литература ===&lt;br /&gt;
*1. П. Кью «Использование UNIX», ISBN 5-8275-0019-4&lt;br /&gt;
*2. В.Г. Олифер, Н.А. Олифер «Сетевые операционные системы», ISBN 5-272-00120-6&lt;br /&gt;
*3. Д. Бэкон, Т. Харрис «Операционные системы», ISBN 5-94723-969-8&lt;br /&gt;
*4. М. Фаулер «Архитектура корпоративных программных приложений», ISBN 5-8459-0579-6&lt;/div&gt;</summary>
		<author><name>Skryabin yuri</name></author>	</entry>

	<entry>
		<id>http://wiki.linuxformat.ru/wiki/LXF87-88:Java</id>
		<title>LXF87-88:Java</title>
		<link rel="alternate" type="text/html" href="http://wiki.linuxformat.ru/wiki/LXF87-88:Java"/>
				<updated>2008-03-17T10:15:50Z</updated>
		
		<summary type="html">&lt;p&gt;Skryabin yuri: /* Реализация потока через Runnable */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=== Потоки в Java ===&lt;br /&gt;
''ЧАСТЬ 4: Завершая курс молодого Java-бойца, '''Антон Черноусов''' научит вас управлять потоками... Жаль, что не денежными.''&lt;br /&gt;
&lt;br /&gt;
C каждым днем появляются все более мощные процессоры, многоядерная архитектура которых стала основной темой ушедшего года, поэтому двухядерный процессор в ноутбуке уже никого не удивляет. С одной стороны – это обстоятельство приближает возможности простого пользователя к возможностям «понастоящему» больших систем. С другой (и рекламные буклеты об этом обычно молчат) – для того, чтобы использовать весь потенциал современных компьютеров, приложение должно «уметь» просчитать задачу фактически на двух или более процессорах. &lt;br /&gt;
&lt;br /&gt;
Создание эффективных алгоритмов для работы на многопроцессорных станциях – это большая и сложная работа. Несмотря на это, для любого программиста актуальна задача организации взаимодействия с медленными ресурсами (например, чтения, записи или копирования файлов, работы с принтером, сетью), так как немногие пользователи смирятся с тем, что их любимая программа «замирает» в момент выполнения какой-либо операции.&lt;br /&gt;
&lt;br /&gt;
Во избежание описанных проблем программа должна использовать потоки или процессы. Под процессом понимается заявка на потребле-&lt;br /&gt;
ние всех видов ресурсов системы, кроме одного – процессорного времени, или иначе говоря, процесс – это запущенная на выполнение программа (такое определение дается в [[LXF87/88:Java#Литература|[1]]]). Поток рассматривается как самостоятельная активность внутри процесса, хотя существуют другие трактовки этого понятия, которые зависят от используемой операционной системы (см., например, [[LXF87/88:Java#Литература|[2]]]). Поток получил свое название по аналогии с потоком команд, поступающих в процессор; при выполнении потоки делят адресное пространство и выделенную память внутри одного процесса. Процессорное время распределяется между различными потоками операционной системой, точнее, одним из компонентов ее ядра – планировщиком. Более полно с понятием процессов и потоков и механизмов работы с ними с точки зрения операционной системы вы можете ознакомиться в книге [[LXF87/88:Java#Литература|[3]]]. &lt;br /&gt;
&lt;br /&gt;
Давайте завершим наш экскурс в теорию и окунемся в реальность Java. Под процессом здесь принято понимать всеобъемлющий контекст выполнения, обеспечивающий высокий уровень изоляции охватываемых им данных от внешнего мира, а под потоком – более «легковесный» активный агент; в контексте одного процесса может функционировать целое множество потоков [[LXF87/88:Java#Литература|[4]]]. Планирование потоков в Java обеспечивается внутренними механизмами JVM.&lt;br /&gt;
&lt;br /&gt;
=== Поток, он же thread ===&lt;br /&gt;
В Java существует два способа работы с потоками: первый заключается в реализации интерфейса Runnable, второй связан с наследованием&lt;br /&gt;
класса Thread, который уже реализует данный интерфейс. В обоих случаях класс должен предоставлять реализацию метода run(). Ниже&lt;br /&gt;
приведен пример класса, реализующего поток через наследование класса Thread:&lt;br /&gt;
&amp;lt;source lang = &amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
public class FirstThread extends Thread {&lt;br /&gt;
  public void run(){&lt;br /&gt;
    for (int i = 1 ; i &amp;lt; 30; i++)&lt;br /&gt;
      System.out.println(&amp;quot;It is in thread &amp;quot;+ i);&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Собственно, метод run() и должен содержать некоторый набор инструкций (разумеется, на языке Java), которые вы хотите выполнить&lt;br /&gt;
в отдельном потоке. Например, если вы реализуете функцию копирования файла (а пользователь, скажем, копирует ISO-образ объемом&lt;br /&gt;
600 Мб), желательно, чтобы эта операция выполнялась в отдельном потоке, запуск которого можно производить следующим образом:&lt;br /&gt;
&amp;lt;source lang = &amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
public class ConsoleToThread {&lt;br /&gt;
  public static void main(String[] args) {&lt;br /&gt;
    FirstThread thread = new FirstThread();&lt;br /&gt;
    thread.start();&lt;br /&gt;
    for (int i = 1; i &amp;lt; 20; i++) {&lt;br /&gt;
      System.out.println(&amp;quot;It is in main &amp;quot; + i);&lt;br /&gt;
    }&lt;br /&gt;
    try {&lt;br /&gt;
      thread.join();&lt;br /&gt;
    } &lt;br /&gt;
    catch (InterruptedException ex) {&lt;br /&gt;
      System.out.println(&amp;quot;Exception in stop thread&amp;quot;);&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
При выполнении метода main() класса ConsoleToThread создается объект-поток FirstThread, который запускается на выполнение методом start() [заметьте – метод run() никогда не вызывается явно, – прим.ред.]. Метод join() используется в случае, когда необходимо «дождаться» завершения потока. Завершение работы потока происходит при выходе из метода run(), как явном (например, посредством return), так и неявном (если внутри метода возникло и не было обработано какое-то исключение).&lt;br /&gt;
&lt;br /&gt;
Имейте в виду (это важно!): повторный запуск уже отработавшего потока приведет к исключению IllegalThreadStateException.&lt;br /&gt;
&lt;br /&gt;
=== Реализация потока через Runnable ===&lt;br /&gt;
Давайте теперь рассмотрим пример работы с потоками через интерфейс Runnable. Если, допустим, класс SameRunnable реализует интерфейс Runnable, то запустить поток на основе этого класса на выполнение можно следующим образом:&lt;br /&gt;
&amp;lt;source lang = &amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
Runnable run = new SameRunnable();&lt;br /&gt;
Thread thread = new Thread(run);&lt;br /&gt;
thread.start();&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
В следующем примере в методе main() класса ConsoleToThreadTwo создается массив threadArray, состоящий из объектов-потоков. При&lt;br /&gt;
этом используется конструктор класса Thread, принимающий два параметра: ссылку на объект, реализующий интерфейс Runnable и&lt;br /&gt;
имя потока:&lt;br /&gt;
&amp;lt;source lang = &amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
Thread thread = new Thread(Runnable, ThreadName);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Метод getName() объекта, реализующего поток, возвращает указанное при создании имя. Обратите внимание, что в нем используется&lt;br /&gt;
статический метод Thread.currentThread(), возвращающий ссылку на объект Thread, соответствующий выполняющемуся в текущий момент&lt;br /&gt;
потоку:&lt;br /&gt;
&amp;lt;source lang = &amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
public class SecondThread implements Runnable {&lt;br /&gt;
  public String getName() {&lt;br /&gt;
    return Thread.currentThread().getName();&lt;br /&gt;
  }&lt;br /&gt;
  public void run() {&lt;br /&gt;
    for (int i = 1; i &amp;lt; 100000; i++) {&lt;br /&gt;
      if ((i % 10000) == 0) {&lt;br /&gt;
        System.out.println(getName() + &amp;quot; counts &amp;quot; + i / 10000);&lt;br /&gt;
      }&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
public class ConsoleToThreadTwo {&lt;br /&gt;
  public static void main(String[] args) {&lt;br /&gt;
    Thread[] threadArray = new Thread[3];&lt;br /&gt;
      for (int i=0; i&amp;lt;threadArray.length; i++){&lt;br /&gt;
        threadArray[i] = new Thread(new SecondThread(), &amp;quot;Thread &amp;quot; + i);&lt;br /&gt;
      }&lt;br /&gt;
      for (int i=0; i&amp;lt;threadArray.length; i++){&lt;br /&gt;
        threadArray[i].start();&lt;br /&gt;
        System.out.println(threadArray[i].getName() + &amp;quot; started&amp;quot;);&lt;br /&gt;
      }&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Проследив за выводом этой программы, можно заметить, что процессорное время распределяется между потоками практически равномерно, однако порядок их выполнения во многом случаен.&lt;br /&gt;
&lt;br /&gt;
=== Приоритеты потоков ===&lt;br /&gt;
=== Потоки-демоны ===&lt;br /&gt;
=== Где искать потоки? ===&lt;br /&gt;
=== Управление потоками ===&lt;br /&gt;
=== Мониторы и синхронизация ===&lt;br /&gt;
=== Взаимные блокировки ===&lt;br /&gt;
=== Литература ===&lt;br /&gt;
*1. П. Кью «Использование UNIX», ISBN 5-8275-0019-4&lt;br /&gt;
*2. В.Г. Олифер, Н.А. Олифер «Сетевые операционные системы», ISBN 5-272-00120-6&lt;br /&gt;
*3. Д. Бэкон, Т. Харрис «Операционные системы», ISBN 5-94723-969-8&lt;br /&gt;
*4. М. Фаулер «Архитектура корпоративных программных приложений», ISBN 5-8459-0579-6&lt;/div&gt;</summary>
		<author><name>Skryabin yuri</name></author>	</entry>

	<entry>
		<id>http://wiki.linuxformat.ru/wiki/LXF87-88:Java</id>
		<title>LXF87-88:Java</title>
		<link rel="alternate" type="text/html" href="http://wiki.linuxformat.ru/wiki/LXF87-88:Java"/>
				<updated>2008-03-17T07:35:05Z</updated>
		
		<summary type="html">&lt;p&gt;Skryabin yuri: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=== Потоки в Java ===&lt;br /&gt;
''ЧАСТЬ 4: Завершая курс молодого Java-бойца, '''Антон Черноусов''' научит вас управлять потоками... Жаль, что не денежными.''&lt;br /&gt;
&lt;br /&gt;
C каждым днем появляются все более мощные процессоры, многоядерная архитектура которых стала основной темой ушедшего года, поэтому двухядерный процессор в ноутбуке уже никого не удивляет. С одной стороны – это обстоятельство приближает возможности простого пользователя к возможностям «понастоящему» больших систем. С другой (и рекламные буклеты об этом обычно молчат) – для того, чтобы использовать весь потенциал современных компьютеров, приложение должно «уметь» просчитать задачу фактически на двух или более процессорах. &lt;br /&gt;
&lt;br /&gt;
Создание эффективных алгоритмов для работы на многопроцессорных станциях – это большая и сложная работа. Несмотря на это, для любого программиста актуальна задача организации взаимодействия с медленными ресурсами (например, чтения, записи или копирования файлов, работы с принтером, сетью), так как немногие пользователи смирятся с тем, что их любимая программа «замирает» в момент выполнения какой-либо операции.&lt;br /&gt;
&lt;br /&gt;
Во избежание описанных проблем программа должна использовать потоки или процессы. Под процессом понимается заявка на потребле-&lt;br /&gt;
ние всех видов ресурсов системы, кроме одного – процессорного времени, или иначе говоря, процесс – это запущенная на выполнение программа (такое определение дается в [[LXF87/88:Java#Литература|[1]]]). Поток рассматривается как самостоятельная активность внутри процесса, хотя существуют другие трактовки этого понятия, которые зависят от используемой операционной системы (см., например, [[LXF87/88:Java#Литература|[2]]]). Поток получил свое название по аналогии с потоком команд, поступающих в процессор; при выполнении потоки делят адресное пространство и выделенную память внутри одного процесса. Процессорное время распределяется между различными потоками операционной системой, точнее, одним из компонентов ее ядра – планировщиком. Более полно с понятием процессов и потоков и механизмов работы с ними с точки зрения операционной системы вы можете ознакомиться в книге [[LXF87/88:Java#Литература|[3]]]. &lt;br /&gt;
&lt;br /&gt;
Давайте завершим наш экскурс в теорию и окунемся в реальность Java. Под процессом здесь принято понимать всеобъемлющий контекст выполнения, обеспечивающий высокий уровень изоляции охватываемых им данных от внешнего мира, а под потоком – более «легковесный» активный агент; в контексте одного процесса может функционировать целое множество потоков [[LXF87/88:Java#Литература|[4]]]. Планирование потоков в Java обеспечивается внутренними механизмами JVM.&lt;br /&gt;
&lt;br /&gt;
=== Поток, он же thread ===&lt;br /&gt;
В Java существует два способа работы с потоками: первый заключается в реализации интерфейса Runnable, второй связан с наследованием&lt;br /&gt;
класса Thread, который уже реализует данный интерфейс. В обоих случаях класс должен предоставлять реализацию метода run(). Ниже&lt;br /&gt;
приведен пример класса, реализующего поток через наследование класса Thread:&lt;br /&gt;
&amp;lt;source lang = &amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
public class FirstThread extends Thread {&lt;br /&gt;
  public void run(){&lt;br /&gt;
    for (int i = 1 ; i &amp;lt; 30; i++)&lt;br /&gt;
      System.out.println(&amp;quot;It is in thread &amp;quot;+ i);&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Собственно, метод run() и должен содержать некоторый набор инструкций (разумеется, на языке Java), которые вы хотите выполнить&lt;br /&gt;
в отдельном потоке. Например, если вы реализуете функцию копирования файла (а пользователь, скажем, копирует ISO-образ объемом&lt;br /&gt;
600 Мб), желательно, чтобы эта операция выполнялась в отдельном потоке, запуск которого можно производить следующим образом:&lt;br /&gt;
&amp;lt;source lang = &amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
public class ConsoleToThread {&lt;br /&gt;
  public static void main(String[] args) {&lt;br /&gt;
    FirstThread thread = new FirstThread();&lt;br /&gt;
    thread.start();&lt;br /&gt;
    for (int i = 1; i &amp;lt; 20; i++) {&lt;br /&gt;
      System.out.println(&amp;quot;It is in main &amp;quot; + i);&lt;br /&gt;
    }&lt;br /&gt;
    try {&lt;br /&gt;
      thread.join();&lt;br /&gt;
    } &lt;br /&gt;
    catch (InterruptedException ex) {&lt;br /&gt;
      System.out.println(&amp;quot;Exception in stop thread&amp;quot;);&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
При выполнении метода main() класса ConsoleToThread создается объект-поток FirstThread, который запускается на выполнение методом start() [заметьте – метод run() никогда не вызывается явно, – прим.ред.]. Метод join() используется в случае, когда необходимо «дождаться» завершения потока. Завершение работы потока происходит при выходе из метода run(), как явном (например, посредством return), так и неявном (если внутри метода возникло и не было обработано какое-то исключение).&lt;br /&gt;
&lt;br /&gt;
Имейте в виду (это важно!): повторный запуск уже отработавшего потока приведет к исключению IllegalThreadStateException.&lt;br /&gt;
&lt;br /&gt;
=== Реализация потока через Runnable ===&lt;br /&gt;
=== Приоритеты потоков ===&lt;br /&gt;
=== Потоки-демоны ===&lt;br /&gt;
=== Где искать потоки? ===&lt;br /&gt;
=== Управление потоками ===&lt;br /&gt;
=== Мониторы и синхронизация ===&lt;br /&gt;
=== Взаимные блокировки ===&lt;br /&gt;
=== Литература ===&lt;br /&gt;
*1. П. Кью «Использование UNIX», ISBN 5-8275-0019-4&lt;br /&gt;
*2. В.Г. Олифер, Н.А. Олифер «Сетевые операционные системы», ISBN 5-272-00120-6&lt;br /&gt;
*3. Д. Бэкон, Т. Харрис «Операционные системы», ISBN 5-94723-969-8&lt;br /&gt;
*4. М. Фаулер «Архитектура корпоративных программных приложений», ISBN 5-8459-0579-6&lt;/div&gt;</summary>
		<author><name>Skryabin yuri</name></author>	</entry>

	<entry>
		<id>http://wiki.linuxformat.ru/wiki/LXF87-88:Java</id>
		<title>LXF87-88:Java</title>
		<link rel="alternate" type="text/html" href="http://wiki.linuxformat.ru/wiki/LXF87-88:Java"/>
				<updated>2008-03-17T07:32:40Z</updated>
		
		<summary type="html">&lt;p&gt;Skryabin yuri: /* Поток, он же thread */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=== Потоки в Java ===&lt;br /&gt;
''ЧАСТЬ 4: Завершая курс молодого Java-бойца, '''Антон Черноусов''' научит вас управлять&lt;br /&gt;
потоками... Жаль, что не денежными.''&lt;br /&gt;
&lt;br /&gt;
C каждым днем появляются все более мощные процессоры, многоядерная архитектура которых стала основной темой ушедшего года, поэтому двухядерный процессор в ноутбуке уже никого не удивляет. С одной стороны – это обстоятельство приближает возможности простого пользователя к возможностям «понастоящему» больших систем. С другой (и рекламные буклеты об этом обычно молчат) – для того, чтобы использовать весь потенциал современных компьютеров, приложение должно «уметь» просчитать задачу фактически на двух или более процессорах. &lt;br /&gt;
&lt;br /&gt;
Создание эффективных алгоритмов для работы на многопроцессорных станциях – это большая и сложная работа. Несмотря на это, для любого программиста актуальна задача организации взаимодействия с медленными ресурсами (например, чтения, записи или копирования файлов, работы с принтером, сетью), так как немногие пользователи смирятся с тем, что их любимая программа «замирает» в момент выполнения какой-либо операции.&lt;br /&gt;
&lt;br /&gt;
Во избежание описанных проблем программа должна использовать потоки или процессы. Под процессом понимается заявка на потребле-&lt;br /&gt;
ние всех видов ресурсов системы, кроме одного – процессорного времени, или иначе говоря, процесс – это запущенная на выполнение программа (такое определение дается в [[LXF87/88:Java#Литература|[1]]]). Поток рассматривается как самостоятельная активность внутри процесса, хотя существуют другие трактовки этого понятия, которые зависят от используемой операционной системы (см., например, [[LXF87/88:Java#Литература|[2]]]). Поток получил свое название по аналогии с потоком команд, поступающих в процессор; при выполнении потоки делят адресное пространство и выделенную память внутри одного процесса. Процессорное время распределяется между различными потоками операционной системой, точнее, одним из компонентов ее ядра – планировщиком. Более полно с понятием процессов и потоков и механизмов работы с ними с точки зрения операционной системы вы можете ознакомиться в книге [[LXF87/88:Java#Литература|[3]]]. &lt;br /&gt;
&lt;br /&gt;
Давайте завершим наш экскурс в теорию и окунемся в реальность Java. Под процессом здесь принято понимать всеобъемлющий контекст выполнения, обеспечивающий высокий уровень изоляции охватываемых им данных от внешнего мира, а под потоком – более «легковесный» активный агент; в контексте одного процесса может функционировать целое множество потоков [[LXF87/88:Java#Литература|[4]]]. Планирование потоков в Java обеспечивается внутренними механизмами JVM.&lt;br /&gt;
&lt;br /&gt;
=== Поток, он же thread ===&lt;br /&gt;
В Java существует два способа работы с потоками: первый заключается в реализации интерфейса Runnable, второй связан с наследованием&lt;br /&gt;
класса Thread, который уже реализует данный интерфейс. В обоих случаях класс должен предоставлять реализацию метода run(). Ниже&lt;br /&gt;
приведен пример класса, реализующего поток через наследование класса Thread:&lt;br /&gt;
&amp;lt;source lang = &amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
public class FirstThread extends Thread {&lt;br /&gt;
  public void run(){&lt;br /&gt;
    for (int i = 1 ; i &amp;lt; 30; i++)&lt;br /&gt;
      System.out.println(&amp;quot;It is in thread &amp;quot;+ i);&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Собственно, метод run() и должен содержать некоторый набор инструкций (разумеется, на языке Java), которые вы хотите выполнить&lt;br /&gt;
в отдельном потоке. Например, если вы реализуете функцию копирования файла (а пользователь, скажем, копирует ISO-образ объемом&lt;br /&gt;
600 Мб), желательно, чтобы эта операция выполнялась в отдельном потоке, запуск которого можно производить следующим образом:&lt;br /&gt;
&amp;lt;source lang = &amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
public class ConsoleToThread {&lt;br /&gt;
  public static void main(String[] args) {&lt;br /&gt;
    FirstThread thread = new FirstThread();&lt;br /&gt;
    thread.start();&lt;br /&gt;
    for (int i = 1; i &amp;lt; 20; i++) {&lt;br /&gt;
      System.out.println(&amp;quot;It is in main &amp;quot; + i);&lt;br /&gt;
    }&lt;br /&gt;
    try {&lt;br /&gt;
      thread.join();&lt;br /&gt;
    } &lt;br /&gt;
    catch (InterruptedException ex) {&lt;br /&gt;
      System.out.println(&amp;quot;Exception in stop thread&amp;quot;);&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
При выполнении метода main() класса ConsoleToThread создается объект-поток FirstThread, который запускается на выполнение методом start() [заметьте – метод run() никогда не вызывается явно, – прим.ред.]. Метод join() используется в случае, когда необходимо «дождаться» завершения потока. Завершение работы потока происходит при выходе из метода run(), как явном (например, посредством return), так и неявном (если внутри метода возникло и не было обработано какое-то исключение).&lt;br /&gt;
&lt;br /&gt;
Имейте в виду (это важно!): повторный запуск уже отработавшего потока приведет к исключению IllegalThreadStateException.&lt;br /&gt;
&lt;br /&gt;
=== Реализация потока через Runnable ===&lt;br /&gt;
=== Приоритеты потоков ===&lt;br /&gt;
=== Потоки-демоны ===&lt;br /&gt;
=== Где искать потоки? ===&lt;br /&gt;
=== Управление потоками ===&lt;br /&gt;
=== Мониторы и синхронизация ===&lt;br /&gt;
=== Взаимные блокировки ===&lt;br /&gt;
=== Литература ===&lt;br /&gt;
*1. П. Кью «Использование UNIX», ISBN 5-8275-0019-4&lt;br /&gt;
*2. В.Г. Олифер, Н.А. Олифер «Сетевые операционные системы», ISBN 5-272-00120-6&lt;br /&gt;
*3. Д. Бэкон, Т. Харрис «Операционные системы», ISBN 5-94723-969-8&lt;br /&gt;
*4. М. Фаулер «Архитектура корпоративных программных приложений», ISBN 5-8459-0579-6&lt;/div&gt;</summary>
		<author><name>Skryabin yuri</name></author>	</entry>

	<entry>
		<id>http://wiki.linuxformat.ru/wiki/LXF87-88:Java</id>
		<title>LXF87-88:Java</title>
		<link rel="alternate" type="text/html" href="http://wiki.linuxformat.ru/wiki/LXF87-88:Java"/>
				<updated>2008-03-17T07:12:20Z</updated>
		
		<summary type="html">&lt;p&gt;Skryabin yuri: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=== Потоки в Java ===&lt;br /&gt;
''ЧАСТЬ 4: Завершая курс молодого Java-бойца, '''Антон Черноусов''' научит вас управлять&lt;br /&gt;
потоками... Жаль, что не денежными.''&lt;br /&gt;
&lt;br /&gt;
C каждым днем появляются все более мощные процессоры, многоядерная архитектура которых стала основной темой ушедшего года, поэтому двухядерный процессор в ноутбуке уже никого не удивляет. С одной стороны – это обстоятельство приближает возможности простого пользователя к возможностям «понастоящему» больших систем. С другой (и рекламные буклеты об этом обычно молчат) – для того, чтобы использовать весь потенциал современных компьютеров, приложение должно «уметь» просчитать задачу фактически на двух или более процессорах. &lt;br /&gt;
&lt;br /&gt;
Создание эффективных алгоритмов для работы на многопроцессорных станциях – это большая и сложная работа. Несмотря на это, для любого программиста актуальна задача организации взаимодействия с медленными ресурсами (например, чтения, записи или копирования файлов, работы с принтером, сетью), так как немногие пользователи смирятся с тем, что их любимая программа «замирает» в момент выполнения какой-либо операции.&lt;br /&gt;
&lt;br /&gt;
Во избежание описанных проблем программа должна использовать потоки или процессы. Под процессом понимается заявка на потребле-&lt;br /&gt;
ние всех видов ресурсов системы, кроме одного – процессорного времени, или иначе говоря, процесс – это запущенная на выполнение программа (такое определение дается в [[LXF87/88:Java#Литература|[1]]]). Поток рассматривается как самостоятельная активность внутри процесса, хотя существуют другие трактовки этого понятия, которые зависят от используемой операционной системы (см., например, [[LXF87/88:Java#Литература|[2]]]). Поток получил свое название по аналогии с потоком команд, поступающих в процессор; при выполнении потоки делят адресное пространство и выделенную память внутри одного процесса. Процессорное время распределяется между различными потоками операционной системой, точнее, одним из компонентов ее ядра – планировщиком. Более полно с понятием процессов и потоков и механизмов работы с ними с точки зрения операционной системы вы можете ознакомиться в книге [[LXF87/88:Java#Литература|[3]]]. &lt;br /&gt;
&lt;br /&gt;
Давайте завершим наш экскурс в теорию и окунемся в реальность Java. Под процессом здесь принято понимать всеобъемлющий контекст выполнения, обеспечивающий высокий уровень изоляции охватываемых им данных от внешнего мира, а под потоком – более «легковесный» активный агент; в контексте одного процесса может функционировать целое множество потоков [[LXF87/88:Java#Литература|[4]]]. Планирование потоков в Java обеспечивается внутренними механизмами JVM.&lt;br /&gt;
&lt;br /&gt;
=== Поток, он же thread ===&lt;br /&gt;
=== Реализация потока через Runnable ===&lt;br /&gt;
=== Приоритеты потоков ===&lt;br /&gt;
=== Потоки-демоны ===&lt;br /&gt;
=== Где искать потоки? ===&lt;br /&gt;
=== Управление потоками ===&lt;br /&gt;
=== Мониторы и синхронизация ===&lt;br /&gt;
=== Взаимные блокировки ===&lt;br /&gt;
=== Литература ===&lt;br /&gt;
*1. П. Кью «Использование UNIX», ISBN 5-8275-0019-4&lt;br /&gt;
*2. В.Г. Олифер, Н.А. Олифер «Сетевые операционные системы», ISBN 5-272-00120-6&lt;br /&gt;
*3. Д. Бэкон, Т. Харрис «Операционные системы», ISBN 5-94723-969-8&lt;br /&gt;
*4. М. Фаулер «Архитектура корпоративных программных приложений», ISBN 5-8459-0579-6&lt;/div&gt;</summary>
		<author><name>Skryabin yuri</name></author>	</entry>

	<entry>
		<id>http://wiki.linuxformat.ru/wiki/LXF87-88:Java</id>
		<title>LXF87-88:Java</title>
		<link rel="alternate" type="text/html" href="http://wiki.linuxformat.ru/wiki/LXF87-88:Java"/>
				<updated>2008-03-17T07:08:17Z</updated>
		
		<summary type="html">&lt;p&gt;Skryabin yuri: Литература&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=== Потоки в Java ===&lt;br /&gt;
''ЧАСТЬ 4: Завершая курс молодого Java-бойца, '''Антон Черноусов''' научит вас управлять&lt;br /&gt;
потоками... Жаль, что не денежными.''&lt;br /&gt;
&lt;br /&gt;
C каждым днем появляются все более мощные процессоры, многоядерная архитектура которых стала основной темой ушедшего года, поэтому двухядерный процессор в ноутбуке уже никого не удивляет. С одной стороны – это обстоятельство приближает возможности простого пользователя к возможностям «понастоящему» больших систем. С другой (и рекламные буклеты об этом обычно молчат) – для того, чтобы использовать весь потенциал современных компьютеров, приложение должно «уметь» просчитать задачу фактически на двух или более процессорах. &lt;br /&gt;
&lt;br /&gt;
Создание эффективных алгоритмов для работы на многопроцессорных станциях – это большая и сложная работа. Несмотря на это, для любого программиста актуальна задача организации взаимодействия с медленными ресурсами (например, чтения, записи или копирования файлов, работы с принтером, сетью), так как немногие пользователи смирятся с тем, что их любимая программа «замирает» в момент выполнения какой-либо операции.&lt;br /&gt;
&lt;br /&gt;
Во избежание описанных проблем программа должна использовать потоки или процессы. Под процессом понимается заявка на потребле-&lt;br /&gt;
ние всех видов ресурсов системы, кроме одного – процессорного времени, или иначе говоря, процесс – это запущенная на выполнение программа (такое определение дается в [[LXF87/88:Java#Литература|[1]]]). Поток рассматривается как самостоятельная активность внутри процесса, хотя существуют другие трактовки этого понятия, которые зависят от используемой операционной системы (см., например, [2]). Поток получил свое название по аналогии с потоком команд, поступающих в процессор; при выполнении потоки делят адресное пространство и выделенную память внутри одного процесса. Процессорное время распределяется между различными потоками операционной системой, точнее, одним из компонентов ее ядра – планировщиком. Более полно с понятием процессов и потоков и механизмов работы с ними с точки зрения операционной системы вы можете ознакомиться в книге [3]. &lt;br /&gt;
&lt;br /&gt;
Давайте завершим наш экскурс в теорию и окунемся в реальность Java. Под процессом здесь принято понимать всеобъемлющий контекст выполнения, обеспечивающий высокий уровень изоляции охватываемых им данных от внешнего мира, а под потоком – более «легковесный» активный агент; в контексте одного процесса может функционировать целое множество потоков [4]. Планирование потоков в Java обеспечивается внутренними механизмами JVM.&lt;br /&gt;
&lt;br /&gt;
=== Поток, он же thread ===&lt;br /&gt;
=== Реализация потока через Runnable ===&lt;br /&gt;
=== Приоритеты потоков ===&lt;br /&gt;
=== Потоки-демоны ===&lt;br /&gt;
=== Где искать потоки? ===&lt;br /&gt;
=== Управление потоками ===&lt;br /&gt;
=== Мониторы и синхронизация ===&lt;br /&gt;
=== Взаимные блокировки ===&lt;br /&gt;
=== Литература ===&lt;br /&gt;
*1. П. Кью «Использование UNIX», ISBN 5-8275-0019-4&lt;br /&gt;
*2. В.Г. Олифер, Н.А. Олифер «Сетевые операционные системы», ISBN 5-272-00120-6&lt;br /&gt;
*3. Д. Бэкон, Т. Харрис «Операционные системы», ISBN 5-94723-969-8&lt;br /&gt;
*4. М. Фаулер «Архитектура корпоративных программных приложений», ISBN 5-8459-0579-6&lt;/div&gt;</summary>
		<author><name>Skryabin yuri</name></author>	</entry>

	<entry>
		<id>http://wiki.linuxformat.ru/wiki/%D0%9E%D0%B1%D1%81%D1%83%D0%B6%D0%B4%D0%B5%D0%BD%D0%B8%D0%B5_%D1%83%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA%D0%B0:Lockal</id>
		<title>Обсуждение участника:Lockal</title>
		<link rel="alternate" type="text/html" href="http://wiki.linuxformat.ru/wiki/%D0%9E%D0%B1%D1%81%D1%83%D0%B6%D0%B4%D0%B5%D0%BD%D0%B8%D0%B5_%D1%83%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA%D0%B0:Lockal"/>
				<updated>2008-03-17T05:59:49Z</updated>
		
		<summary type="html">&lt;p&gt;Skryabin yuri: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Сэр, я хоть и с опозданием (не было нета), но приступил к работе.&lt;br /&gt;
Спасибо, конечно, за помощь, но этот номер зарегистрирован за мной.&lt;br /&gt;
: Без проблем, хотя я начал[http://wiki.linuxformat.ru/index.php?title=LXF85&amp;amp;action=history] работать над номером, когда он был ещё свободен[http://wiki.linuxformat.ru/?oldid=623]. А пока я займусь другими номерами. --[[Участник:Lockal|Lockal]] 19:16, 16 марта 2008 (MSK)&lt;br /&gt;
&lt;br /&gt;
Не хочу показаться интервентом - могу переслать письмо от Валентина Синицына от 6 марта, где за мной утвердили 85-ый номер. --[[Участник:flagist0|flagist0]]&lt;br /&gt;
&lt;br /&gt;
'''LXF84''' Спасибо за статью по LaTeX, но этот номер (LXF 84) занят, и я хотел бы завершить работу над ним самостоятельно&lt;br /&gt;
[[Участник:Skryabin yuri|Skryabin yuri]]&lt;/div&gt;</summary>
		<author><name>Skryabin yuri</name></author>	</entry>

	<entry>
		<id>http://wiki.linuxformat.ru/wiki/%D0%9E%D0%B1%D1%81%D1%83%D0%B6%D0%B4%D0%B5%D0%BD%D0%B8%D0%B5_%D1%83%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA%D0%B0:Lockal</id>
		<title>Обсуждение участника:Lockal</title>
		<link rel="alternate" type="text/html" href="http://wiki.linuxformat.ru/wiki/%D0%9E%D0%B1%D1%81%D1%83%D0%B6%D0%B4%D0%B5%D0%BD%D0%B8%D0%B5_%D1%83%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA%D0%B0:Lockal"/>
				<updated>2008-03-17T05:51:25Z</updated>
		
		<summary type="html">&lt;p&gt;Skryabin yuri: New section: LXF84&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Сэр, я хоть и с опозданием (не было нета), но приступил к работе.&lt;br /&gt;
Спасибо, конечно, за помощь, но этот номер зарегистрирован за мной.&lt;br /&gt;
: Без проблем, хотя я начал[http://wiki.linuxformat.ru/index.php?title=LXF85&amp;amp;action=history] работать над номером, когда он был ещё свободен[http://wiki.linuxformat.ru/?oldid=623]. А пока я займусь другими номерами. --[[Участник:Lockal|Lockal]] 19:16, 16 марта 2008 (MSK)&lt;br /&gt;
&lt;br /&gt;
Не хочу показаться интервентом - могу переслать письмо от Валентина Синицына от 6 марта, где за мной утвердили 85-ый номер. --[[Участник:flagist0|flagist0]]&lt;br /&gt;
&lt;br /&gt;
== LXF84 ==&lt;br /&gt;
&lt;br /&gt;
Спасибо за статью по LaTeX, но этот номер (LXF 84) занят, и я хотел бы завершить работу над ним самостоятельно&lt;/div&gt;</summary>
		<author><name>Skryabin yuri</name></author>	</entry>

	<entry>
		<id>http://wiki.linuxformat.ru/wiki/LXF87-88</id>
		<title>LXF87-88</title>
		<link rel="alternate" type="text/html" href="http://wiki.linuxformat.ru/wiki/LXF87-88"/>
				<updated>2008-03-14T13:28:47Z</updated>
		
		<summary type="html">&lt;p&gt;Skryabin yuri: Изменена ссылка на учебник Java&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==Linux Format 1 (87/88), Январь 2008==&lt;br /&gt;
===Обзоры===&lt;br /&gt;
* [[LXF87/88:Fedora_Core_6_vs_Ubuntu_6.10|Fedora Core 6 vs Ubuntu 6.10]]&lt;br /&gt;
* [[LXF87/88:FreeBSD_6.2|FreeBSD 6.2]]&lt;br /&gt;
* [[LXF87/88:Mandriva_Powerpack_2007|Mandriva Powerpack 2007]]&lt;br /&gt;
* [[LXF87/88:Oxygen|Oxygen]]&lt;br /&gt;
* [[LXF87/88:Valgrind|Valgrind]]&lt;br /&gt;
=== Учебники ===&lt;br /&gt;
* [[LXF87/88:Java|Потоки в Java]]&lt;br /&gt;
Не удивляйтесь – программисты Java тоже&lt;br /&gt;
хотят выполнять много задач одновременно.&lt;/div&gt;</summary>
		<author><name>Skryabin yuri</name></author>	</entry>

	<entry>
		<id>http://wiki.linuxformat.ru/wiki/LXF87-88</id>
		<title>LXF87-88</title>
		<link rel="alternate" type="text/html" href="http://wiki.linuxformat.ru/wiki/LXF87-88"/>
				<updated>2008-03-14T13:27:27Z</updated>
		
		<summary type="html">&lt;p&gt;Skryabin yuri: Изменена ссылка на учебник Java&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==Linux Format 1 (87/88), Январь 2008==&lt;br /&gt;
===Обзоры===&lt;br /&gt;
* [[LXF87/88:Fedora_Core_6_vs_Ubuntu_6.10|Fedora Core 6 vs Ubuntu 6.10]]&lt;br /&gt;
* [[LXF87/88:FreeBSD_6.2|FreeBSD 6.2]]&lt;br /&gt;
* [[LXF87/88:Mandriva_Powerpack_2007|Mandriva Powerpack 2007]]&lt;br /&gt;
* [[LXF87/88:Oxygen|Oxygen]]&lt;br /&gt;
* [[LXF87/88:Valgrind|Valgrind]]&lt;br /&gt;
=== Учебники ===&lt;br /&gt;
* [[LXF87/88:Java|Потоки Java]]&lt;br /&gt;
Не удивляйтесь – программисты Java тоже&lt;br /&gt;
хотят выполнять много задач одновременно.&lt;/div&gt;</summary>
		<author><name>Skryabin yuri</name></author>	</entry>

	<entry>
		<id>http://wiki.linuxformat.ru/wiki/LXF87-88:Java</id>
		<title>LXF87-88:Java</title>
		<link rel="alternate" type="text/html" href="http://wiki.linuxformat.ru/wiki/LXF87-88:Java"/>
				<updated>2008-03-14T13:24:38Z</updated>
		
		<summary type="html">&lt;p&gt;Skryabin yuri: Начало, содержание&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=== Потоки в Java ===&lt;br /&gt;
''ЧАСТЬ 4: Завершая курс молодого Java-бойца, '''Антон Черноусов''' научит вас управлять&lt;br /&gt;
потоками... Жаль, что не денежными.''&lt;br /&gt;
&lt;br /&gt;
C каждым днем появляются все более мощные процессоры, многоядерная архитектура которых стала основной темой ушедшего года, поэтому двухядерный процессор в ноутбуке уже никого не удивляет. С одной стороны – это обстоятельство приближает возможности простого пользователя к возможностям «понастоящему» больших систем. С другой (и рекламные буклеты об этом обычно молчат) – для того, чтобы использовать весь потенциал современных компьютеров, приложение должно «уметь» просчитать задачу фактически на двух или более процессорах. &lt;br /&gt;
&lt;br /&gt;
Создание эффективных алгоритмов для работы на многопроцессорных станциях – это большая и сложная работа. Несмотря на это, для любого программиста актуальна задача организации взаимодействия с медленными ресурсами (например, чтения, записи или копирования файлов, работы с принтером, сетью), так как немногие пользователи смирятся с тем, что их любимая программа «замирает» в момент выполнения какой-либо операции.&lt;br /&gt;
&lt;br /&gt;
Во избежание описанных проблем программа должна использовать потоки или процессы. Под процессом понимается заявка на потребле-&lt;br /&gt;
ние всех видов ресурсов системы, кроме одного – процессорного времени, или иначе говоря, процесс – это запущенная на выполнение программа (такое определение дается в [1]). Поток рассматривается как самостоятельная активность внутри процесса, хотя существуют другие трактовки этого понятия, которые зависят от используемой операционной системы (см., например, [2]). Поток получил свое название по аналогии с потоком команд, поступающих в процессор; при выполнении потоки делят адресное пространство и выделенную память внутри одного процесса. Процессорное время распределяется между различными потоками операционной системой, точнее, одним из компонентов ее ядра – планировщиком. Более полно с понятием процессов и потоков и механизмов работы с ними с точки зрения операционной системы вы можете ознакомиться в книге [3]. &lt;br /&gt;
&lt;br /&gt;
Давайте завершим наш экскурс в теорию и окунемся в реальность Java. Под процессом здесь принято понимать всеобъемлющий контекст выполнения, обеспечивающий высокий уровень изоляции охватываемых им данных от внешнего мира, а под потоком – более «легковесный» активный агент; в контексте одного процесса может функционировать целое множество потоков [4]. Планирование потоков в Java обеспечивается внутренними механизмами JVM.&lt;br /&gt;
&lt;br /&gt;
=== Поток, он же thread ===&lt;br /&gt;
=== Реализация потока через Runnable ===&lt;br /&gt;
=== Приоритеты потоков ===&lt;br /&gt;
=== Потоки-демоны ===&lt;br /&gt;
=== Где искать потоки? ===&lt;br /&gt;
=== Управление потоками ===&lt;br /&gt;
=== Мониторы и синхронизация ===&lt;br /&gt;
=== Взаимные блокировки ===&lt;/div&gt;</summary>
		<author><name>Skryabin yuri</name></author>	</entry>

	<entry>
		<id>http://wiki.linuxformat.ru/wiki/LXF87-88</id>
		<title>LXF87-88</title>
		<link rel="alternate" type="text/html" href="http://wiki.linuxformat.ru/wiki/LXF87-88"/>
				<updated>2008-03-14T13:12:47Z</updated>
		
		<summary type="html">&lt;p&gt;Skryabin yuri: Добавлена ссылка на учебник Java&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==Linux Format 1 (87/88), Январь 2008==&lt;br /&gt;
===Обзоры===&lt;br /&gt;
* [[LXF87/88:Fedora_Core_6_vs_Ubuntu_6.10|Fedora Core 6 vs Ubuntu 6.10]]&lt;br /&gt;
* [[LXF87/88:FreeBSD_6.2|FreeBSD 6.2]]&lt;br /&gt;
* [[LXF87/88:Mandriva_Powerpack_2007|Mandriva Powerpack 2007]]&lt;br /&gt;
* [[LXF87/88:Oxygen|Oxygen]]&lt;br /&gt;
* [[LXF87/88:Valgrind|Valgrind]]&lt;br /&gt;
=== Учебники ===&lt;br /&gt;
* [[LXF87/88:Java|Снова о потоках]]&lt;br /&gt;
Не удивляйтесь – программисты Java тоже&lt;br /&gt;
хотят выполнять много задач одновременно.&lt;/div&gt;</summary>
		<author><name>Skryabin yuri</name></author>	</entry>

	<entry>
		<id>http://wiki.linuxformat.ru/wiki/LXF86:Java</id>
		<title>LXF86:Java</title>
		<link rel="alternate" type="text/html" href="http://wiki.linuxformat.ru/wiki/LXF86:Java"/>
				<updated>2008-03-13T10:37:03Z</updated>
		
		<summary type="html">&lt;p&gt;Skryabin yuri: /* Извлечение данных из XML-документа */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=== Хранение данных ===&lt;br /&gt;
''ЧАСТЬ 3: Даже самой замечательной программе надо откуда-то черпать данные для своей работы. Данные, как известно, хранятся в файлах. Тему продолжает '''Антон Черноусов'''.''&lt;br /&gt;
&lt;br /&gt;
В предыдущей статье из цикла, посвященного программированию на Java, были рассмотрены вопросы организации простых вычислений, ветвлений, циклов, а также генерации и обработки исключений.&lt;br /&gt;
&lt;br /&gt;
В течение третьего урока мы поговорим о работе с файлами, о протоколировании работы программы и коснемся методов работы с&lt;br /&gt;
XML-данными.&lt;br /&gt;
&lt;br /&gt;
=== Файлы — потоки ===&lt;br /&gt;
Сказочное королевство под руководством царевны Несмеяны (так как cупруг практически всегда отсутствовал), благодаря талантам и приобретенным навыкам, стало разрастаться, и результаты полюдья просто-напросто перестали помещаться в семейный чулан. Чтобы накапливать и хранить богатства, потребовались дополнительные помещения, роль которых для нас привычно играют файлы.&lt;br /&gt;
&lt;br /&gt;
Отношение к файлам в Java достаточно непростое: если рассматривать файл как устройство для ввода/вывода информации — с этой точ&lt;br /&gt;
ки зрения он подобен блоку памяти или экрану, интерфейс доступа к которому унифицирован: это поток. Но несмотря на унифицированный интерфейс, существует большое количество классов сходной функциональности, в которых легко запутаться.&lt;br /&gt;
&lt;br /&gt;
Поток можно представить в виде ленточного конвейера с последовательным размещением или извлечением данных, при использовании&lt;br /&gt;
которого задача программиста сводиться к осуществлению операций «поместить/читать» данные, а остальные детали реализации скрыты&lt;br /&gt;
от него.&lt;br /&gt;
&lt;br /&gt;
=== Чтение данных ===&lt;br /&gt;
Разнообразие классов для работы с файлами позволяет выбрать для себя ту связку, которая больше нравится. Лично я для чтения данных использую BufferedReader, InputStreamReader и FileInputStream. Собственно взаимодействие этих классов для программиста заканчивается в момент создания экземпляра BufferedReader, что делается следующим образом:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang = &amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
BufferedReader br = null;&lt;br /&gt;
br = new BufferedReader(new InputStreamReader(new FileInputStream(pathToFile), encoding));&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
В процессе создания участвуют строковые переменные, содержащие путь к файлу и кодировку, в которой производится считывание&lt;br /&gt;
данных: pathToFile и encoding. В классах, работающих с файлами, считается обязательным создавать переменную для кодировки по умолчанию:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang = &amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
protected static String DEFAULT_ENCODING = &amp;quot;UTF-8&amp;quot;;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Любой текстовый файл можно представить себе в виде набора строк, поэтому давайте реализуем метод для считывания содержимого&lt;br /&gt;
файла в массив String[]. Далее представлен метод rippedCurrentFile(path ToFile, encoding) класса FileRipper, который извлекает данные из файла с помощью метода readLine() экземпляра класса BufferedReader:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang = &amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
protected boolean rippedCurrentFile(String pathToFile, String encoding) {&lt;br /&gt;
  // connecting to file&lt;br /&gt;
  BufferedReader br = null;&lt;br /&gt;
  try {&lt;br /&gt;
    br = new BufferedReader(new InputStreamReader(new FileInputStream(pathToFile),encoding));&lt;br /&gt;
  } &lt;br /&gt;
  catch (UnsupportedEncodingException e) {&lt;br /&gt;
    this.error = FILE_ERROR_UNSUPPORTED_ENCODING; return false;&lt;br /&gt;
  } &lt;br /&gt;
  catch (FileNotFoundException e) {&lt;br /&gt;
    this.error = FILE_ERROR_NO_FILE; return false;&lt;br /&gt;
  }&lt;br /&gt;
  // ripping the file&lt;br /&gt;
  String str = null;&lt;br /&gt;
  ArrayList allStrings = new ArrayList();&lt;br /&gt;
  try {&lt;br /&gt;
    while (!(str = br.readLine()).equals(null)) { allStrings.add(str); }&lt;br /&gt;
  } &lt;br /&gt;
  catch (IOException e) {&lt;br /&gt;
    this.error = FILE_ERROR_IO_READ; return false;&lt;br /&gt;
  } &lt;br /&gt;
  catch (NullPointerException e) {&lt;br /&gt;
    this.error = FILE_ERROR_END_OF_FILE;&lt;br /&gt;
  }&lt;br /&gt;
  // free the resources&lt;br /&gt;
  try {&lt;br /&gt;
    br.close();&lt;br /&gt;
  } &lt;br /&gt;
  catch (IOException e) {&lt;br /&gt;
    this.error = FILE_ERROR_IO_CLOSE; return false;&lt;br /&gt;
  }&lt;br /&gt;
  this.allStrings = (String[]) allStrings.toArray(new String[0]); &lt;br /&gt;
  return true;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Полный код примера, в том числе код класса ConsoleToFileRipper, применяющий экземпляр класса FileRipper для извлечения данных из файла, можно найти на диске в каталоге '''examples 1'''.&lt;br /&gt;
&lt;br /&gt;
=== Запись данных ===&lt;br /&gt;
Процесс записи данных в файл хоть и отличается от чтения, но тоже достаточно похож на организацию конвейера. Для записи&lt;br /&gt;
я обычно использую связку BufferedWriter, OutputStreamWriter, FileOutputStream.&lt;br /&gt;
&amp;lt;source lang = &amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
BufferedWriter out;&lt;br /&gt;
out = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(pathToFile), encoding));&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Для освобождения ресурсов, которые используют экземпляры классов BufferedReader и BufferedWriter, необходимо вызвать метод&lt;br /&gt;
close().&lt;br /&gt;
&lt;br /&gt;
Далее приведу простой пример метода, который записывает строковый массив в файл (полный код метода расположен на диске в&lt;br /&gt;
директории '''examples 2'''):&lt;br /&gt;
&amp;lt;source lang = &amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
public boolean createCurrentFile(String pathToFile, String[] allStrings, String encoding){&lt;br /&gt;
  try {&lt;br /&gt;
    BufferedWriter out;&lt;br /&gt;
    out = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(pathToFile), encoding));&lt;br /&gt;
    for (int i = 0; i &amp;lt; allStrings.length; i++) {&lt;br /&gt;
      out.write(allStrings[i]); out.write(‘\n’);&lt;br /&gt;
    }&lt;br /&gt;
    out.close();&lt;br /&gt;
  } &lt;br /&gt;
  catch (IOException e) {&lt;br /&gt;
    e.printStackTrace(); &lt;br /&gt;
    return false;&lt;br /&gt;
  }&lt;br /&gt;
  return true;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Свободный доступ ===&lt;br /&gt;
В представленных ранее примерах доступ к данным осуществляется последовательно, что не всегда удобно (хотя в большинстве случаев именно такой доступ и используется). Для осуществления чтения и записи данных из файла в произвольном порядке существует специальный класс RandomAccessFile, экземпляр которого создается следующим образом:&lt;br /&gt;
&amp;lt;source lang = &amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
RandomAccessFile raf = new RandomAccessFile(pathToFile, mode);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
При этом pathToFile — путь до файла, а mode — режим работы. mode может принимать значения: r (только чтение), rw (чтение-запись), rws (чтение-запись с синхронным сохранением содержимого и метаданных), rwd (чтение-запись с синхронным сохранением содержимого файла). К сожалению, кодировку указать нельзя. Огромным преимуществом подхода является то, что с помощью метода getFilePointer() можно узнать текущее месторасположение указателя, а с помощью метода seek() можно передвинуть указатель в необходимое место в файле. Я предпочитаю не использовать данный класс — считайте это личным предубеждением.&lt;br /&gt;
&lt;br /&gt;
=== Протоколирование работы программы ===&lt;br /&gt;
Для контроля и анализа работы приложения существуют методы протоколирования. Популярным инструментом для этих целей в мире&lt;br /&gt;
Java является библиотека Log4j, которая разрабатывается в Apache Software Foundation. Текущую версию можно загрузить с [http://logging.apache.org/[http://logging.apache.org/]].&lt;br /&gt;
&lt;br /&gt;
Для использования библиотеки необходимо создать конфигурационный файл, который описывает, что, куда и как нужно протоколировать. Log4j имеет три базовые составляющие: logger, appender и layout.&lt;br /&gt;
&lt;br /&gt;
layout — это элементы, определяющие вид и содержание записей. Изначально имеется несколько заранее созданных layout-ов, а в случае необходимости можно создать свой собственный.&lt;br /&gt;
&lt;br /&gt;
Appender — это элемент, определяющий местоположение протокола, с его помощью задается тип протоколирования:&lt;br /&gt;
* файловое протоколирование (FileAppender);&lt;br /&gt;
* консольное протоколирование (ConsoleAppender);&lt;br /&gt;
* протоколирование в базы данных (JDBCAppender);&lt;br /&gt;
* протоколирование на SMTP-сервера (SMTPAppender) и др.&lt;br /&gt;
&lt;br /&gt;
Logger — это элемент, который обеспечивает протоколирование какого-либо события. Если обратиться к ранее приведенной аналогии&lt;br /&gt;
ленточного конвейера, logger — это и есть тот самый конвейер, вызывая методы которого, мы формируем протокол работы программы.&lt;br /&gt;
Элемент logger предусматривает следующие уровни протоколирования: DEBUG, INFO, WARN, ERROR, FATAL; уровням соответствуют методы класса org.apache.log4j.Logger: debug; info; warn; error; fatal.&lt;br /&gt;
&lt;br /&gt;
Ниже представлен пример записей для конфигурационного файла нашего приложения, которые нужно сохранить в файл с названием '''log.properties''' (название файла может быть любым).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 log4j.logger.simple=DEBUG, nameLogAppender&lt;br /&gt;
 log4j.appender.nameLogAppender=org.apache.log4j.FileAppender&lt;br /&gt;
 log4j.appender.nameLogAppender.File=nameLogFile.log&lt;br /&gt;
 log4j.appender.nameLogAppender.layout=org.apache.log4j.SimpleLayout&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Первая строка указывает используемый уровень logger (DEBUG) и appender (nameLogAppender). Далее идут настройки appender: указание типа — FileAppender. В третьей строке указываем путь до файла журнала, а в последней — формат записи. Использовать экземпляр класса Logger можно примерно так (пример протоколирования приведен на диске в каталоге '''examples 3'''):&lt;br /&gt;
&amp;lt;source lang = &amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
File propertiesFile = new File(&amp;quot;log.properties&amp;quot;);&lt;br /&gt;
PropertyConfigurator.configure(propertiesFile.toString());&lt;br /&gt;
Logger logger = Logger.getLogger(&amp;quot;simple&amp;quot;);&lt;br /&gt;
logger.info(&amp;quot;the program has started&amp;quot;);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Документы XML ===&lt;br /&gt;
Проектируя и создавая ПО, невозможно не столкнутся с миром XML (Extensible Markup Language). XML был создан в недрах World Wide&lt;br /&gt;
Web Consortium (W3C) для преодоления ограничений языка HTML. Можно сказать, что HTML — один из самых успешных языков, область&lt;br /&gt;
его использования с каждым годом растет (в основном в объемах). Несмотря на это, почему же W3C создал XML, и зачем вам использовать этот язык? В чем ограниченность HTML? Ответ на эти вопросы один:XML был создан для обеспечения взаимодействия разнородных систем.&lt;br /&gt;
&lt;br /&gt;
HTML, как и любой другой текстовый язык, не позволяет перенести смысл тех данных, которые он хранит. XML был разработан для решения этой задачи с прицелом на Web, но получился таким удачным, что его стали использовать практически везде. Суть XML в том, что он хранит семантический смысл данных, поэтому выполнив анализ такого XML-документа, система может «понять» полученные данные. В Интернете существует большое количество информации, посвященной XML (например, [http://www.ibm.com/developerworks/xml/[www.ibm.com/developerworks/xml/]]), поэтому не будем подробно останавливаться на его преимуществах, а сразу приступим к использованию.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang = &amp;quot;xml&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;?xml version=&amp;quot;1.0&amp;quot; ?&amp;gt;&lt;br /&gt;
&amp;lt;line name=&amp;quot;firstLine&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;point id=&amp;quot;1&amp;quot; theX=&amp;quot;1&amp;quot; theY=&amp;quot;1&amp;quot;/&amp;gt;&lt;br /&gt;
&amp;lt;point id=&amp;quot;2&amp;quot; theX=&amp;quot;2&amp;quot; theY=&amp;quot;2&amp;quot;/&amp;gt;&lt;br /&gt;
&amp;lt;/line&amp;gt;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Выше приведен простой пример XML-документа, содержащего корневой элемент line, который, в свою очередь, содержит два узла с&lt;br /&gt;
тремя атрибутами (id, theX, theY) каждый.&lt;br /&gt;
&lt;br /&gt;
=== Создание XML-документа ===&lt;br /&gt;
Говоря про создание XML-документа, я подразумеваю создание дерева XML-документа в памяти системы, то есть объекта DOM (Document Object Model). DOM была создана W3C, и это – официальная Рекомендация консорциума. В противовес DOM существует SAX (Simple API for XML). С моделью SAX можно ознакомиться более подробно в &lt;br /&gt;
[http://www-128.ibm.com/developerworks/ru/views/xml/libraryview.jsp[http://www-128.ibm.com/developerworks/ru/views/xml/libraryview.jsp]]. Основная разница между методами заключается в том, что DOM обеспечивает виртуальное представление XML-файла в памяти системы, в то время как SAX – это событийная модель обработки, в которой в момент встречи определенного элемента вызывается соответствующее событие.&lt;br /&gt;
&lt;br /&gt;
Для создания «отображения» XML-файла в памяти системы необходимо воспользоваться классом Document, экземпляр которого можно получить следующим образом:&lt;br /&gt;
&amp;lt;source lang = &amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();&lt;br /&gt;
DocumentBuilder db = dbf.newDocumentBuilder();&lt;br /&gt;
Document doc = db.newDocument();&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Создание корневого узла XML документа можно выполняется так:&lt;br /&gt;
&amp;lt;source lang = &amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
Element root = doc.createElement(&amp;quot;line&amp;quot;);&lt;br /&gt;
root.setAttribute(&amp;quot;name&amp;quot;, &amp;quot;firstLine&amp;quot;);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
С помощью метода createElement(name) производится создание элементов, в то время как создание и установка значений атрибутов&lt;br /&gt;
элементов производится с помощью метода setAttribute(name, value), где name – имя атрибута, а value – его значение. С помощью метода appendChild можно добавить узел в элемент или произвести запись элемента в документ XML, например, так:&lt;br /&gt;
&amp;lt;source lang = &amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
root.appendChild(item);&lt;br /&gt;
doc.appendChild(root);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Более детально процесс создания XML документа на примере класса Line изложен в директории '''examples 4'''. При вызове метода&lt;br /&gt;
createDoc() этого класса создается экземпляр класса Document, идентичный приведенному ранее коду XML.&lt;br /&gt;
&lt;br /&gt;
=== Сохранение XML-документа ===&lt;br /&gt;
Для сохранения созданного в памяти документа предлагаю воспользоваться методом saveXML(docToSave, pathToFile, charSet). В процессе сохранения участвует уже знакомый нам OutputStreamWriter, а также экземпляр класса Transformer, который обеспечивает преобразование объекта DOMSource в выходной поток.&lt;br /&gt;
&amp;lt;source lang = &amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
public void saveXML(Document docToSave, String pathToFile, String charSet) {&lt;br /&gt;
  try {&lt;br /&gt;
    Writer target = new OutputStreamWriter(new FileOutputStream(pathToFile), charSet);&lt;br /&gt;
    Source source = new DOMSource(docToSave);&lt;br /&gt;
    StreamResult dest = new StreamResult(target);&lt;br /&gt;
    Transformer t = TransformerFactory.newInstance().newTransformer();&lt;br /&gt;
    t.setOutputProperty(OutputKeys.ENCODING, charSet);&lt;br /&gt;
    t.setOutputProperty(OutputKeys.INDENT, &amp;quot;yes&amp;quot;);&lt;br /&gt;
    t.transform(source, dest);  &lt;br /&gt;
    target.flush();&lt;br /&gt;
    target.close();&lt;br /&gt;
  } &lt;br /&gt;
  catch (Exception ex) {&lt;br /&gt;
    ex.printStackTrace();&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Реализация этого метода представлена на диске в директории '''examples 5'''.&lt;br /&gt;
&lt;br /&gt;
=== Загрузка XML-документа ===&lt;br /&gt;
Подобно сохранению XLM-документа, загрузка также достаточно просто выполняется с помощью экземпляра класса FileInputStream. Используя DocumentBuilderFactory, сгенерируем объект класса Document следующим образом:&lt;br /&gt;
&amp;lt;source lang = &amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
FileInputStream fis = new FileInputStream(pathToFile);&lt;br /&gt;
Document doc = DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(fis);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Фактически, создание документа происходит вследствие выполнения метода parse. Для детально рассмотрения процесса загрузки&lt;br /&gt;
XML документа обратитесь к директории '''examples 6''', расположенной на диске.&lt;br /&gt;
&lt;br /&gt;
=== Извлечение данных из XML-документа ===&lt;br /&gt;
Итак, что же делать с Document? Работать, естественно! Прежде чем приступить к обработке XML-документа, хочу обратить внимание на одну неприятную особенность: почти всегда XML документ содержит пустые узлы или символы перевода каретки (неизбежное зло форматирования). К сожалению, такая особенность существенно затрудняет процесс обработки XML-документа. Поэтому следует всегда проводить нормализацию с помощью определенного в интерфейсе метода normalize(), или, если реализация Document не имеет такой возможности или нормализация выполняется некорректно – воспользуйтесь методом normalizeDocument класса FileXMLReader (вы найдете его все в той же директории '''examples 6'''). Вызвать данный метод можно следующим образом:&lt;br /&gt;
&amp;lt;source lang = &amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
normalizeDocument(doc.getDocumentElement());&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Изложенный выше материал получился несколько другого формата, нежели предыдущие статьи. Статья содержит небольшие примеры&lt;br /&gt;
и отсылает на набор сознательно упрощенных готовых решений, благодаря которым вы сможете работать с файлами, производить прото-&lt;br /&gt;
колирование деятельности вашего приложения, начать работать с данными в формате XML. Цель приведенных примеров – обеспечить вас&lt;br /&gt;
необходимым минимумом информации и дать направление для поиска ответов на Ваши вопросы.&lt;/div&gt;</summary>
		<author><name>Skryabin yuri</name></author>	</entry>

	<entry>
		<id>http://wiki.linuxformat.ru/wiki/LXF86:Java</id>
		<title>LXF86:Java</title>
		<link rel="alternate" type="text/html" href="http://wiki.linuxformat.ru/wiki/LXF86:Java"/>
				<updated>2008-03-13T10:34:45Z</updated>
		
		<summary type="html">&lt;p&gt;Skryabin yuri: /* Загрузка XML-документа */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=== Хранение данных ===&lt;br /&gt;
''ЧАСТЬ 3: Даже самой замечательной программе надо откуда-то черпать данные для своей работы. Данные, как известно, хранятся в файлах. Тему продолжает '''Антон Черноусов'''.''&lt;br /&gt;
&lt;br /&gt;
В предыдущей статье из цикла, посвященного программированию на Java, были рассмотрены вопросы организации простых вычислений, ветвлений, циклов, а также генерации и обработки исключений.&lt;br /&gt;
&lt;br /&gt;
В течение третьего урока мы поговорим о работе с файлами, о протоколировании работы программы и коснемся методов работы с&lt;br /&gt;
XML-данными.&lt;br /&gt;
&lt;br /&gt;
=== Файлы — потоки ===&lt;br /&gt;
Сказочное королевство под руководством царевны Несмеяны (так как cупруг практически всегда отсутствовал), благодаря талантам и приобретенным навыкам, стало разрастаться, и результаты полюдья просто-напросто перестали помещаться в семейный чулан. Чтобы накапливать и хранить богатства, потребовались дополнительные помещения, роль которых для нас привычно играют файлы.&lt;br /&gt;
&lt;br /&gt;
Отношение к файлам в Java достаточно непростое: если рассматривать файл как устройство для ввода/вывода информации — с этой точ&lt;br /&gt;
ки зрения он подобен блоку памяти или экрану, интерфейс доступа к которому унифицирован: это поток. Но несмотря на унифицированный интерфейс, существует большое количество классов сходной функциональности, в которых легко запутаться.&lt;br /&gt;
&lt;br /&gt;
Поток можно представить в виде ленточного конвейера с последовательным размещением или извлечением данных, при использовании&lt;br /&gt;
которого задача программиста сводиться к осуществлению операций «поместить/читать» данные, а остальные детали реализации скрыты&lt;br /&gt;
от него.&lt;br /&gt;
&lt;br /&gt;
=== Чтение данных ===&lt;br /&gt;
Разнообразие классов для работы с файлами позволяет выбрать для себя ту связку, которая больше нравится. Лично я для чтения данных использую BufferedReader, InputStreamReader и FileInputStream. Собственно взаимодействие этих классов для программиста заканчивается в момент создания экземпляра BufferedReader, что делается следующим образом:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang = &amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
BufferedReader br = null;&lt;br /&gt;
br = new BufferedReader(new InputStreamReader(new FileInputStream(pathToFile), encoding));&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
В процессе создания участвуют строковые переменные, содержащие путь к файлу и кодировку, в которой производится считывание&lt;br /&gt;
данных: pathToFile и encoding. В классах, работающих с файлами, считается обязательным создавать переменную для кодировки по умолчанию:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang = &amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
protected static String DEFAULT_ENCODING = &amp;quot;UTF-8&amp;quot;;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Любой текстовый файл можно представить себе в виде набора строк, поэтому давайте реализуем метод для считывания содержимого&lt;br /&gt;
файла в массив String[]. Далее представлен метод rippedCurrentFile(path ToFile, encoding) класса FileRipper, который извлекает данные из файла с помощью метода readLine() экземпляра класса BufferedReader:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang = &amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
protected boolean rippedCurrentFile(String pathToFile, String encoding) {&lt;br /&gt;
  // connecting to file&lt;br /&gt;
  BufferedReader br = null;&lt;br /&gt;
  try {&lt;br /&gt;
    br = new BufferedReader(new InputStreamReader(new FileInputStream(pathToFile),encoding));&lt;br /&gt;
  } &lt;br /&gt;
  catch (UnsupportedEncodingException e) {&lt;br /&gt;
    this.error = FILE_ERROR_UNSUPPORTED_ENCODING; return false;&lt;br /&gt;
  } &lt;br /&gt;
  catch (FileNotFoundException e) {&lt;br /&gt;
    this.error = FILE_ERROR_NO_FILE; return false;&lt;br /&gt;
  }&lt;br /&gt;
  // ripping the file&lt;br /&gt;
  String str = null;&lt;br /&gt;
  ArrayList allStrings = new ArrayList();&lt;br /&gt;
  try {&lt;br /&gt;
    while (!(str = br.readLine()).equals(null)) { allStrings.add(str); }&lt;br /&gt;
  } &lt;br /&gt;
  catch (IOException e) {&lt;br /&gt;
    this.error = FILE_ERROR_IO_READ; return false;&lt;br /&gt;
  } &lt;br /&gt;
  catch (NullPointerException e) {&lt;br /&gt;
    this.error = FILE_ERROR_END_OF_FILE;&lt;br /&gt;
  }&lt;br /&gt;
  // free the resources&lt;br /&gt;
  try {&lt;br /&gt;
    br.close();&lt;br /&gt;
  } &lt;br /&gt;
  catch (IOException e) {&lt;br /&gt;
    this.error = FILE_ERROR_IO_CLOSE; return false;&lt;br /&gt;
  }&lt;br /&gt;
  this.allStrings = (String[]) allStrings.toArray(new String[0]); &lt;br /&gt;
  return true;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Полный код примера, в том числе код класса ConsoleToFileRipper, применяющий экземпляр класса FileRipper для извлечения данных из файла, можно найти на диске в каталоге '''examples 1'''.&lt;br /&gt;
&lt;br /&gt;
=== Запись данных ===&lt;br /&gt;
Процесс записи данных в файл хоть и отличается от чтения, но тоже достаточно похож на организацию конвейера. Для записи&lt;br /&gt;
я обычно использую связку BufferedWriter, OutputStreamWriter, FileOutputStream.&lt;br /&gt;
&amp;lt;source lang = &amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
BufferedWriter out;&lt;br /&gt;
out = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(pathToFile), encoding));&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Для освобождения ресурсов, которые используют экземпляры классов BufferedReader и BufferedWriter, необходимо вызвать метод&lt;br /&gt;
close().&lt;br /&gt;
&lt;br /&gt;
Далее приведу простой пример метода, который записывает строковый массив в файл (полный код метода расположен на диске в&lt;br /&gt;
директории '''examples 2'''):&lt;br /&gt;
&amp;lt;source lang = &amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
public boolean createCurrentFile(String pathToFile, String[] allStrings, String encoding){&lt;br /&gt;
  try {&lt;br /&gt;
    BufferedWriter out;&lt;br /&gt;
    out = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(pathToFile), encoding));&lt;br /&gt;
    for (int i = 0; i &amp;lt; allStrings.length; i++) {&lt;br /&gt;
      out.write(allStrings[i]); out.write(‘\n’);&lt;br /&gt;
    }&lt;br /&gt;
    out.close();&lt;br /&gt;
  } &lt;br /&gt;
  catch (IOException e) {&lt;br /&gt;
    e.printStackTrace(); &lt;br /&gt;
    return false;&lt;br /&gt;
  }&lt;br /&gt;
  return true;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Свободный доступ ===&lt;br /&gt;
В представленных ранее примерах доступ к данным осуществляется последовательно, что не всегда удобно (хотя в большинстве случаев именно такой доступ и используется). Для осуществления чтения и записи данных из файла в произвольном порядке существует специальный класс RandomAccessFile, экземпляр которого создается следующим образом:&lt;br /&gt;
&amp;lt;source lang = &amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
RandomAccessFile raf = new RandomAccessFile(pathToFile, mode);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
При этом pathToFile — путь до файла, а mode — режим работы. mode может принимать значения: r (только чтение), rw (чтение-запись), rws (чтение-запись с синхронным сохранением содержимого и метаданных), rwd (чтение-запись с синхронным сохранением содержимого файла). К сожалению, кодировку указать нельзя. Огромным преимуществом подхода является то, что с помощью метода getFilePointer() можно узнать текущее месторасположение указателя, а с помощью метода seek() можно передвинуть указатель в необходимое место в файле. Я предпочитаю не использовать данный класс — считайте это личным предубеждением.&lt;br /&gt;
&lt;br /&gt;
=== Протоколирование работы программы ===&lt;br /&gt;
Для контроля и анализа работы приложения существуют методы протоколирования. Популярным инструментом для этих целей в мире&lt;br /&gt;
Java является библиотека Log4j, которая разрабатывается в Apache Software Foundation. Текущую версию можно загрузить с [http://logging.apache.org/[http://logging.apache.org/]].&lt;br /&gt;
&lt;br /&gt;
Для использования библиотеки необходимо создать конфигурационный файл, который описывает, что, куда и как нужно протоколировать. Log4j имеет три базовые составляющие: logger, appender и layout.&lt;br /&gt;
&lt;br /&gt;
layout — это элементы, определяющие вид и содержание записей. Изначально имеется несколько заранее созданных layout-ов, а в случае необходимости можно создать свой собственный.&lt;br /&gt;
&lt;br /&gt;
Appender — это элемент, определяющий местоположение протокола, с его помощью задается тип протоколирования:&lt;br /&gt;
* файловое протоколирование (FileAppender);&lt;br /&gt;
* консольное протоколирование (ConsoleAppender);&lt;br /&gt;
* протоколирование в базы данных (JDBCAppender);&lt;br /&gt;
* протоколирование на SMTP-сервера (SMTPAppender) и др.&lt;br /&gt;
&lt;br /&gt;
Logger — это элемент, который обеспечивает протоколирование какого-либо события. Если обратиться к ранее приведенной аналогии&lt;br /&gt;
ленточного конвейера, logger — это и есть тот самый конвейер, вызывая методы которого, мы формируем протокол работы программы.&lt;br /&gt;
Элемент logger предусматривает следующие уровни протоколирования: DEBUG, INFO, WARN, ERROR, FATAL; уровням соответствуют методы класса org.apache.log4j.Logger: debug; info; warn; error; fatal.&lt;br /&gt;
&lt;br /&gt;
Ниже представлен пример записей для конфигурационного файла нашего приложения, которые нужно сохранить в файл с названием '''log.properties''' (название файла может быть любым).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 log4j.logger.simple=DEBUG, nameLogAppender&lt;br /&gt;
 log4j.appender.nameLogAppender=org.apache.log4j.FileAppender&lt;br /&gt;
 log4j.appender.nameLogAppender.File=nameLogFile.log&lt;br /&gt;
 log4j.appender.nameLogAppender.layout=org.apache.log4j.SimpleLayout&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Первая строка указывает используемый уровень logger (DEBUG) и appender (nameLogAppender). Далее идут настройки appender: указание типа — FileAppender. В третьей строке указываем путь до файла журнала, а в последней — формат записи. Использовать экземпляр класса Logger можно примерно так (пример протоколирования приведен на диске в каталоге '''examples 3'''):&lt;br /&gt;
&amp;lt;source lang = &amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
File propertiesFile = new File(&amp;quot;log.properties&amp;quot;);&lt;br /&gt;
PropertyConfigurator.configure(propertiesFile.toString());&lt;br /&gt;
Logger logger = Logger.getLogger(&amp;quot;simple&amp;quot;);&lt;br /&gt;
logger.info(&amp;quot;the program has started&amp;quot;);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Документы XML ===&lt;br /&gt;
Проектируя и создавая ПО, невозможно не столкнутся с миром XML (Extensible Markup Language). XML был создан в недрах World Wide&lt;br /&gt;
Web Consortium (W3C) для преодоления ограничений языка HTML. Можно сказать, что HTML — один из самых успешных языков, область&lt;br /&gt;
его использования с каждым годом растет (в основном в объемах). Несмотря на это, почему же W3C создал XML, и зачем вам использовать этот язык? В чем ограниченность HTML? Ответ на эти вопросы один:XML был создан для обеспечения взаимодействия разнородных систем.&lt;br /&gt;
&lt;br /&gt;
HTML, как и любой другой текстовый язык, не позволяет перенести смысл тех данных, которые он хранит. XML был разработан для решения этой задачи с прицелом на Web, но получился таким удачным, что его стали использовать практически везде. Суть XML в том, что он хранит семантический смысл данных, поэтому выполнив анализ такого XML-документа, система может «понять» полученные данные. В Интернете существует большое количество информации, посвященной XML (например, [http://www.ibm.com/developerworks/xml/[www.ibm.com/developerworks/xml/]]), поэтому не будем подробно останавливаться на его преимуществах, а сразу приступим к использованию.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang = &amp;quot;xml&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;?xml version=&amp;quot;1.0&amp;quot; ?&amp;gt;&lt;br /&gt;
&amp;lt;line name=&amp;quot;firstLine&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;point id=&amp;quot;1&amp;quot; theX=&amp;quot;1&amp;quot; theY=&amp;quot;1&amp;quot;/&amp;gt;&lt;br /&gt;
&amp;lt;point id=&amp;quot;2&amp;quot; theX=&amp;quot;2&amp;quot; theY=&amp;quot;2&amp;quot;/&amp;gt;&lt;br /&gt;
&amp;lt;/line&amp;gt;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Выше приведен простой пример XML-документа, содержащего корневой элемент line, который, в свою очередь, содержит два узла с&lt;br /&gt;
тремя атрибутами (id, theX, theY) каждый.&lt;br /&gt;
&lt;br /&gt;
=== Создание XML-документа ===&lt;br /&gt;
Говоря про создание XML-документа, я подразумеваю создание дерева XML-документа в памяти системы, то есть объекта DOM (Document Object Model). DOM была создана W3C, и это – официальная Рекомендация консорциума. В противовес DOM существует SAX (Simple API for XML). С моделью SAX можно ознакомиться более подробно в &lt;br /&gt;
[http://www-128.ibm.com/developerworks/ru/views/xml/libraryview.jsp[http://www-128.ibm.com/developerworks/ru/views/xml/libraryview.jsp]]. Основная разница между методами заключается в том, что DOM обеспечивает виртуальное представление XML-файла в памяти системы, в то время как SAX – это событийная модель обработки, в которой в момент встречи определенного элемента вызывается соответствующее событие.&lt;br /&gt;
&lt;br /&gt;
Для создания «отображения» XML-файла в памяти системы необходимо воспользоваться классом Document, экземпляр которого можно получить следующим образом:&lt;br /&gt;
&amp;lt;source lang = &amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();&lt;br /&gt;
DocumentBuilder db = dbf.newDocumentBuilder();&lt;br /&gt;
Document doc = db.newDocument();&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Создание корневого узла XML документа можно выполняется так:&lt;br /&gt;
&amp;lt;source lang = &amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
Element root = doc.createElement(&amp;quot;line&amp;quot;);&lt;br /&gt;
root.setAttribute(&amp;quot;name&amp;quot;, &amp;quot;firstLine&amp;quot;);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
С помощью метода createElement(name) производится создание элементов, в то время как создание и установка значений атрибутов&lt;br /&gt;
элементов производится с помощью метода setAttribute(name, value), где name – имя атрибута, а value – его значение. С помощью метода appendChild можно добавить узел в элемент или произвести запись элемента в документ XML, например, так:&lt;br /&gt;
&amp;lt;source lang = &amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
root.appendChild(item);&lt;br /&gt;
doc.appendChild(root);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Более детально процесс создания XML документа на примере класса Line изложен в директории '''examples 4'''. При вызове метода&lt;br /&gt;
createDoc() этого класса создается экземпляр класса Document, идентичный приведенному ранее коду XML.&lt;br /&gt;
&lt;br /&gt;
=== Сохранение XML-документа ===&lt;br /&gt;
Для сохранения созданного в памяти документа предлагаю воспользоваться методом saveXML(docToSave, pathToFile, charSet). В процессе сохранения участвует уже знакомый нам OutputStreamWriter, а также экземпляр класса Transformer, который обеспечивает преобразование объекта DOMSource в выходной поток.&lt;br /&gt;
&amp;lt;source lang = &amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
public void saveXML(Document docToSave, String pathToFile, String charSet) {&lt;br /&gt;
  try {&lt;br /&gt;
    Writer target = new OutputStreamWriter(new FileOutputStream(pathToFile), charSet);&lt;br /&gt;
    Source source = new DOMSource(docToSave);&lt;br /&gt;
    StreamResult dest = new StreamResult(target);&lt;br /&gt;
    Transformer t = TransformerFactory.newInstance().newTransformer();&lt;br /&gt;
    t.setOutputProperty(OutputKeys.ENCODING, charSet);&lt;br /&gt;
    t.setOutputProperty(OutputKeys.INDENT, &amp;quot;yes&amp;quot;);&lt;br /&gt;
    t.transform(source, dest);  &lt;br /&gt;
    target.flush();&lt;br /&gt;
    target.close();&lt;br /&gt;
  } &lt;br /&gt;
  catch (Exception ex) {&lt;br /&gt;
    ex.printStackTrace();&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Реализация этого метода представлена на диске в директории '''examples 5'''.&lt;br /&gt;
&lt;br /&gt;
=== Загрузка XML-документа ===&lt;br /&gt;
Подобно сохранению XLM-документа, загрузка также достаточно просто выполняется с помощью экземпляра класса FileInputStream. Используя DocumentBuilderFactory, сгенерируем объект класса Document следующим образом:&lt;br /&gt;
&amp;lt;source lang = &amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
FileInputStream fis = new FileInputStream(pathToFile);&lt;br /&gt;
Document doc = DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(fis);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Фактически, создание документа происходит вследствие выполнения метода parse. Для детально рассмотрения процесса загрузки&lt;br /&gt;
XML документа обратитесь к директории '''examples 6''', расположенной на диске.&lt;br /&gt;
&lt;br /&gt;
=== Извлечение данных из XML-документа ===&lt;/div&gt;</summary>
		<author><name>Skryabin yuri</name></author>	</entry>

	<entry>
		<id>http://wiki.linuxformat.ru/wiki/LXF86:Java</id>
		<title>LXF86:Java</title>
		<link rel="alternate" type="text/html" href="http://wiki.linuxformat.ru/wiki/LXF86:Java"/>
				<updated>2008-03-13T10:32:41Z</updated>
		
		<summary type="html">&lt;p&gt;Skryabin yuri: /* Сохранение XML-документа */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=== Хранение данных ===&lt;br /&gt;
''ЧАСТЬ 3: Даже самой замечательной программе надо откуда-то черпать данные для своей работы. Данные, как известно, хранятся в файлах. Тему продолжает '''Антон Черноусов'''.''&lt;br /&gt;
&lt;br /&gt;
В предыдущей статье из цикла, посвященного программированию на Java, были рассмотрены вопросы организации простых вычислений, ветвлений, циклов, а также генерации и обработки исключений.&lt;br /&gt;
&lt;br /&gt;
В течение третьего урока мы поговорим о работе с файлами, о протоколировании работы программы и коснемся методов работы с&lt;br /&gt;
XML-данными.&lt;br /&gt;
&lt;br /&gt;
=== Файлы — потоки ===&lt;br /&gt;
Сказочное королевство под руководством царевны Несмеяны (так как cупруг практически всегда отсутствовал), благодаря талантам и приобретенным навыкам, стало разрастаться, и результаты полюдья просто-напросто перестали помещаться в семейный чулан. Чтобы накапливать и хранить богатства, потребовались дополнительные помещения, роль которых для нас привычно играют файлы.&lt;br /&gt;
&lt;br /&gt;
Отношение к файлам в Java достаточно непростое: если рассматривать файл как устройство для ввода/вывода информации — с этой точ&lt;br /&gt;
ки зрения он подобен блоку памяти или экрану, интерфейс доступа к которому унифицирован: это поток. Но несмотря на унифицированный интерфейс, существует большое количество классов сходной функциональности, в которых легко запутаться.&lt;br /&gt;
&lt;br /&gt;
Поток можно представить в виде ленточного конвейера с последовательным размещением или извлечением данных, при использовании&lt;br /&gt;
которого задача программиста сводиться к осуществлению операций «поместить/читать» данные, а остальные детали реализации скрыты&lt;br /&gt;
от него.&lt;br /&gt;
&lt;br /&gt;
=== Чтение данных ===&lt;br /&gt;
Разнообразие классов для работы с файлами позволяет выбрать для себя ту связку, которая больше нравится. Лично я для чтения данных использую BufferedReader, InputStreamReader и FileInputStream. Собственно взаимодействие этих классов для программиста заканчивается в момент создания экземпляра BufferedReader, что делается следующим образом:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang = &amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
BufferedReader br = null;&lt;br /&gt;
br = new BufferedReader(new InputStreamReader(new FileInputStream(pathToFile), encoding));&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
В процессе создания участвуют строковые переменные, содержащие путь к файлу и кодировку, в которой производится считывание&lt;br /&gt;
данных: pathToFile и encoding. В классах, работающих с файлами, считается обязательным создавать переменную для кодировки по умолчанию:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang = &amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
protected static String DEFAULT_ENCODING = &amp;quot;UTF-8&amp;quot;;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Любой текстовый файл можно представить себе в виде набора строк, поэтому давайте реализуем метод для считывания содержимого&lt;br /&gt;
файла в массив String[]. Далее представлен метод rippedCurrentFile(path ToFile, encoding) класса FileRipper, который извлекает данные из файла с помощью метода readLine() экземпляра класса BufferedReader:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang = &amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
protected boolean rippedCurrentFile(String pathToFile, String encoding) {&lt;br /&gt;
  // connecting to file&lt;br /&gt;
  BufferedReader br = null;&lt;br /&gt;
  try {&lt;br /&gt;
    br = new BufferedReader(new InputStreamReader(new FileInputStream(pathToFile),encoding));&lt;br /&gt;
  } &lt;br /&gt;
  catch (UnsupportedEncodingException e) {&lt;br /&gt;
    this.error = FILE_ERROR_UNSUPPORTED_ENCODING; return false;&lt;br /&gt;
  } &lt;br /&gt;
  catch (FileNotFoundException e) {&lt;br /&gt;
    this.error = FILE_ERROR_NO_FILE; return false;&lt;br /&gt;
  }&lt;br /&gt;
  // ripping the file&lt;br /&gt;
  String str = null;&lt;br /&gt;
  ArrayList allStrings = new ArrayList();&lt;br /&gt;
  try {&lt;br /&gt;
    while (!(str = br.readLine()).equals(null)) { allStrings.add(str); }&lt;br /&gt;
  } &lt;br /&gt;
  catch (IOException e) {&lt;br /&gt;
    this.error = FILE_ERROR_IO_READ; return false;&lt;br /&gt;
  } &lt;br /&gt;
  catch (NullPointerException e) {&lt;br /&gt;
    this.error = FILE_ERROR_END_OF_FILE;&lt;br /&gt;
  }&lt;br /&gt;
  // free the resources&lt;br /&gt;
  try {&lt;br /&gt;
    br.close();&lt;br /&gt;
  } &lt;br /&gt;
  catch (IOException e) {&lt;br /&gt;
    this.error = FILE_ERROR_IO_CLOSE; return false;&lt;br /&gt;
  }&lt;br /&gt;
  this.allStrings = (String[]) allStrings.toArray(new String[0]); &lt;br /&gt;
  return true;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Полный код примера, в том числе код класса ConsoleToFileRipper, применяющий экземпляр класса FileRipper для извлечения данных из файла, можно найти на диске в каталоге '''examples 1'''.&lt;br /&gt;
&lt;br /&gt;
=== Запись данных ===&lt;br /&gt;
Процесс записи данных в файл хоть и отличается от чтения, но тоже достаточно похож на организацию конвейера. Для записи&lt;br /&gt;
я обычно использую связку BufferedWriter, OutputStreamWriter, FileOutputStream.&lt;br /&gt;
&amp;lt;source lang = &amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
BufferedWriter out;&lt;br /&gt;
out = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(pathToFile), encoding));&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Для освобождения ресурсов, которые используют экземпляры классов BufferedReader и BufferedWriter, необходимо вызвать метод&lt;br /&gt;
close().&lt;br /&gt;
&lt;br /&gt;
Далее приведу простой пример метода, который записывает строковый массив в файл (полный код метода расположен на диске в&lt;br /&gt;
директории '''examples 2'''):&lt;br /&gt;
&amp;lt;source lang = &amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
public boolean createCurrentFile(String pathToFile, String[] allStrings, String encoding){&lt;br /&gt;
  try {&lt;br /&gt;
    BufferedWriter out;&lt;br /&gt;
    out = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(pathToFile), encoding));&lt;br /&gt;
    for (int i = 0; i &amp;lt; allStrings.length; i++) {&lt;br /&gt;
      out.write(allStrings[i]); out.write(‘\n’);&lt;br /&gt;
    }&lt;br /&gt;
    out.close();&lt;br /&gt;
  } &lt;br /&gt;
  catch (IOException e) {&lt;br /&gt;
    e.printStackTrace(); &lt;br /&gt;
    return false;&lt;br /&gt;
  }&lt;br /&gt;
  return true;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Свободный доступ ===&lt;br /&gt;
В представленных ранее примерах доступ к данным осуществляется последовательно, что не всегда удобно (хотя в большинстве случаев именно такой доступ и используется). Для осуществления чтения и записи данных из файла в произвольном порядке существует специальный класс RandomAccessFile, экземпляр которого создается следующим образом:&lt;br /&gt;
&amp;lt;source lang = &amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
RandomAccessFile raf = new RandomAccessFile(pathToFile, mode);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
При этом pathToFile — путь до файла, а mode — режим работы. mode может принимать значения: r (только чтение), rw (чтение-запись), rws (чтение-запись с синхронным сохранением содержимого и метаданных), rwd (чтение-запись с синхронным сохранением содержимого файла). К сожалению, кодировку указать нельзя. Огромным преимуществом подхода является то, что с помощью метода getFilePointer() можно узнать текущее месторасположение указателя, а с помощью метода seek() можно передвинуть указатель в необходимое место в файле. Я предпочитаю не использовать данный класс — считайте это личным предубеждением.&lt;br /&gt;
&lt;br /&gt;
=== Протоколирование работы программы ===&lt;br /&gt;
Для контроля и анализа работы приложения существуют методы протоколирования. Популярным инструментом для этих целей в мире&lt;br /&gt;
Java является библиотека Log4j, которая разрабатывается в Apache Software Foundation. Текущую версию можно загрузить с [http://logging.apache.org/[http://logging.apache.org/]].&lt;br /&gt;
&lt;br /&gt;
Для использования библиотеки необходимо создать конфигурационный файл, который описывает, что, куда и как нужно протоколировать. Log4j имеет три базовые составляющие: logger, appender и layout.&lt;br /&gt;
&lt;br /&gt;
layout — это элементы, определяющие вид и содержание записей. Изначально имеется несколько заранее созданных layout-ов, а в случае необходимости можно создать свой собственный.&lt;br /&gt;
&lt;br /&gt;
Appender — это элемент, определяющий местоположение протокола, с его помощью задается тип протоколирования:&lt;br /&gt;
* файловое протоколирование (FileAppender);&lt;br /&gt;
* консольное протоколирование (ConsoleAppender);&lt;br /&gt;
* протоколирование в базы данных (JDBCAppender);&lt;br /&gt;
* протоколирование на SMTP-сервера (SMTPAppender) и др.&lt;br /&gt;
&lt;br /&gt;
Logger — это элемент, который обеспечивает протоколирование какого-либо события. Если обратиться к ранее приведенной аналогии&lt;br /&gt;
ленточного конвейера, logger — это и есть тот самый конвейер, вызывая методы которого, мы формируем протокол работы программы.&lt;br /&gt;
Элемент logger предусматривает следующие уровни протоколирования: DEBUG, INFO, WARN, ERROR, FATAL; уровням соответствуют методы класса org.apache.log4j.Logger: debug; info; warn; error; fatal.&lt;br /&gt;
&lt;br /&gt;
Ниже представлен пример записей для конфигурационного файла нашего приложения, которые нужно сохранить в файл с названием '''log.properties''' (название файла может быть любым).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 log4j.logger.simple=DEBUG, nameLogAppender&lt;br /&gt;
 log4j.appender.nameLogAppender=org.apache.log4j.FileAppender&lt;br /&gt;
 log4j.appender.nameLogAppender.File=nameLogFile.log&lt;br /&gt;
 log4j.appender.nameLogAppender.layout=org.apache.log4j.SimpleLayout&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Первая строка указывает используемый уровень logger (DEBUG) и appender (nameLogAppender). Далее идут настройки appender: указание типа — FileAppender. В третьей строке указываем путь до файла журнала, а в последней — формат записи. Использовать экземпляр класса Logger можно примерно так (пример протоколирования приведен на диске в каталоге '''examples 3'''):&lt;br /&gt;
&amp;lt;source lang = &amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
File propertiesFile = new File(&amp;quot;log.properties&amp;quot;);&lt;br /&gt;
PropertyConfigurator.configure(propertiesFile.toString());&lt;br /&gt;
Logger logger = Logger.getLogger(&amp;quot;simple&amp;quot;);&lt;br /&gt;
logger.info(&amp;quot;the program has started&amp;quot;);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Документы XML ===&lt;br /&gt;
Проектируя и создавая ПО, невозможно не столкнутся с миром XML (Extensible Markup Language). XML был создан в недрах World Wide&lt;br /&gt;
Web Consortium (W3C) для преодоления ограничений языка HTML. Можно сказать, что HTML — один из самых успешных языков, область&lt;br /&gt;
его использования с каждым годом растет (в основном в объемах). Несмотря на это, почему же W3C создал XML, и зачем вам использовать этот язык? В чем ограниченность HTML? Ответ на эти вопросы один:XML был создан для обеспечения взаимодействия разнородных систем.&lt;br /&gt;
&lt;br /&gt;
HTML, как и любой другой текстовый язык, не позволяет перенести смысл тех данных, которые он хранит. XML был разработан для решения этой задачи с прицелом на Web, но получился таким удачным, что его стали использовать практически везде. Суть XML в том, что он хранит семантический смысл данных, поэтому выполнив анализ такого XML-документа, система может «понять» полученные данные. В Интернете существует большое количество информации, посвященной XML (например, [http://www.ibm.com/developerworks/xml/[www.ibm.com/developerworks/xml/]]), поэтому не будем подробно останавливаться на его преимуществах, а сразу приступим к использованию.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang = &amp;quot;xml&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;?xml version=&amp;quot;1.0&amp;quot; ?&amp;gt;&lt;br /&gt;
&amp;lt;line name=&amp;quot;firstLine&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;point id=&amp;quot;1&amp;quot; theX=&amp;quot;1&amp;quot; theY=&amp;quot;1&amp;quot;/&amp;gt;&lt;br /&gt;
&amp;lt;point id=&amp;quot;2&amp;quot; theX=&amp;quot;2&amp;quot; theY=&amp;quot;2&amp;quot;/&amp;gt;&lt;br /&gt;
&amp;lt;/line&amp;gt;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Выше приведен простой пример XML-документа, содержащего корневой элемент line, который, в свою очередь, содержит два узла с&lt;br /&gt;
тремя атрибутами (id, theX, theY) каждый.&lt;br /&gt;
&lt;br /&gt;
=== Создание XML-документа ===&lt;br /&gt;
Говоря про создание XML-документа, я подразумеваю создание дерева XML-документа в памяти системы, то есть объекта DOM (Document Object Model). DOM была создана W3C, и это – официальная Рекомендация консорциума. В противовес DOM существует SAX (Simple API for XML). С моделью SAX можно ознакомиться более подробно в &lt;br /&gt;
[http://www-128.ibm.com/developerworks/ru/views/xml/libraryview.jsp[http://www-128.ibm.com/developerworks/ru/views/xml/libraryview.jsp]]. Основная разница между методами заключается в том, что DOM обеспечивает виртуальное представление XML-файла в памяти системы, в то время как SAX – это событийная модель обработки, в которой в момент встречи определенного элемента вызывается соответствующее событие.&lt;br /&gt;
&lt;br /&gt;
Для создания «отображения» XML-файла в памяти системы необходимо воспользоваться классом Document, экземпляр которого можно получить следующим образом:&lt;br /&gt;
&amp;lt;source lang = &amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();&lt;br /&gt;
DocumentBuilder db = dbf.newDocumentBuilder();&lt;br /&gt;
Document doc = db.newDocument();&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Создание корневого узла XML документа можно выполняется так:&lt;br /&gt;
&amp;lt;source lang = &amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
Element root = doc.createElement(&amp;quot;line&amp;quot;);&lt;br /&gt;
root.setAttribute(&amp;quot;name&amp;quot;, &amp;quot;firstLine&amp;quot;);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
С помощью метода createElement(name) производится создание элементов, в то время как создание и установка значений атрибутов&lt;br /&gt;
элементов производится с помощью метода setAttribute(name, value), где name – имя атрибута, а value – его значение. С помощью метода appendChild можно добавить узел в элемент или произвести запись элемента в документ XML, например, так:&lt;br /&gt;
&amp;lt;source lang = &amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
root.appendChild(item);&lt;br /&gt;
doc.appendChild(root);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Более детально процесс создания XML документа на примере класса Line изложен в директории '''examples 4'''. При вызове метода&lt;br /&gt;
createDoc() этого класса создается экземпляр класса Document, идентичный приведенному ранее коду XML.&lt;br /&gt;
&lt;br /&gt;
=== Сохранение XML-документа ===&lt;br /&gt;
Для сохранения созданного в памяти документа предлагаю воспользоваться методом saveXML(docToSave, pathToFile, charSet). В процессе сохранения участвует уже знакомый нам OutputStreamWriter, а также экземпляр класса Transformer, который обеспечивает преобразование объекта DOMSource в выходной поток.&lt;br /&gt;
&amp;lt;source lang = &amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
public void saveXML(Document docToSave, String pathToFile, String charSet) {&lt;br /&gt;
  try {&lt;br /&gt;
    Writer target = new OutputStreamWriter(new FileOutputStream(pathToFile), charSet);&lt;br /&gt;
    Source source = new DOMSource(docToSave);&lt;br /&gt;
    StreamResult dest = new StreamResult(target);&lt;br /&gt;
    Transformer t = TransformerFactory.newInstance().newTransformer();&lt;br /&gt;
    t.setOutputProperty(OutputKeys.ENCODING, charSet);&lt;br /&gt;
    t.setOutputProperty(OutputKeys.INDENT, &amp;quot;yes&amp;quot;);&lt;br /&gt;
    t.transform(source, dest);  &lt;br /&gt;
    target.flush();&lt;br /&gt;
    target.close();&lt;br /&gt;
  } &lt;br /&gt;
  catch (Exception ex) {&lt;br /&gt;
    ex.printStackTrace();&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Реализация этого метода представлена на диске в директории '''examples 5'''.&lt;br /&gt;
&lt;br /&gt;
=== Загрузка XML-документа ===&lt;br /&gt;
&lt;br /&gt;
=== Извлечение данных из XML-документа ===&lt;/div&gt;</summary>
		<author><name>Skryabin yuri</name></author>	</entry>

	<entry>
		<id>http://wiki.linuxformat.ru/wiki/LXF86:Java</id>
		<title>LXF86:Java</title>
		<link rel="alternate" type="text/html" href="http://wiki.linuxformat.ru/wiki/LXF86:Java"/>
				<updated>2008-03-13T10:32:17Z</updated>
		
		<summary type="html">&lt;p&gt;Skryabin yuri: /* Сохранение XML-документа */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=== Хранение данных ===&lt;br /&gt;
''ЧАСТЬ 3: Даже самой замечательной программе надо откуда-то черпать данные для своей работы. Данные, как известно, хранятся в файлах. Тему продолжает '''Антон Черноусов'''.''&lt;br /&gt;
&lt;br /&gt;
В предыдущей статье из цикла, посвященного программированию на Java, были рассмотрены вопросы организации простых вычислений, ветвлений, циклов, а также генерации и обработки исключений.&lt;br /&gt;
&lt;br /&gt;
В течение третьего урока мы поговорим о работе с файлами, о протоколировании работы программы и коснемся методов работы с&lt;br /&gt;
XML-данными.&lt;br /&gt;
&lt;br /&gt;
=== Файлы — потоки ===&lt;br /&gt;
Сказочное королевство под руководством царевны Несмеяны (так как cупруг практически всегда отсутствовал), благодаря талантам и приобретенным навыкам, стало разрастаться, и результаты полюдья просто-напросто перестали помещаться в семейный чулан. Чтобы накапливать и хранить богатства, потребовались дополнительные помещения, роль которых для нас привычно играют файлы.&lt;br /&gt;
&lt;br /&gt;
Отношение к файлам в Java достаточно непростое: если рассматривать файл как устройство для ввода/вывода информации — с этой точ&lt;br /&gt;
ки зрения он подобен блоку памяти или экрану, интерфейс доступа к которому унифицирован: это поток. Но несмотря на унифицированный интерфейс, существует большое количество классов сходной функциональности, в которых легко запутаться.&lt;br /&gt;
&lt;br /&gt;
Поток можно представить в виде ленточного конвейера с последовательным размещением или извлечением данных, при использовании&lt;br /&gt;
которого задача программиста сводиться к осуществлению операций «поместить/читать» данные, а остальные детали реализации скрыты&lt;br /&gt;
от него.&lt;br /&gt;
&lt;br /&gt;
=== Чтение данных ===&lt;br /&gt;
Разнообразие классов для работы с файлами позволяет выбрать для себя ту связку, которая больше нравится. Лично я для чтения данных использую BufferedReader, InputStreamReader и FileInputStream. Собственно взаимодействие этих классов для программиста заканчивается в момент создания экземпляра BufferedReader, что делается следующим образом:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang = &amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
BufferedReader br = null;&lt;br /&gt;
br = new BufferedReader(new InputStreamReader(new FileInputStream(pathToFile), encoding));&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
В процессе создания участвуют строковые переменные, содержащие путь к файлу и кодировку, в которой производится считывание&lt;br /&gt;
данных: pathToFile и encoding. В классах, работающих с файлами, считается обязательным создавать переменную для кодировки по умолчанию:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang = &amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
protected static String DEFAULT_ENCODING = &amp;quot;UTF-8&amp;quot;;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Любой текстовый файл можно представить себе в виде набора строк, поэтому давайте реализуем метод для считывания содержимого&lt;br /&gt;
файла в массив String[]. Далее представлен метод rippedCurrentFile(path ToFile, encoding) класса FileRipper, который извлекает данные из файла с помощью метода readLine() экземпляра класса BufferedReader:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang = &amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
protected boolean rippedCurrentFile(String pathToFile, String encoding) {&lt;br /&gt;
  // connecting to file&lt;br /&gt;
  BufferedReader br = null;&lt;br /&gt;
  try {&lt;br /&gt;
    br = new BufferedReader(new InputStreamReader(new FileInputStream(pathToFile),encoding));&lt;br /&gt;
  } &lt;br /&gt;
  catch (UnsupportedEncodingException e) {&lt;br /&gt;
    this.error = FILE_ERROR_UNSUPPORTED_ENCODING; return false;&lt;br /&gt;
  } &lt;br /&gt;
  catch (FileNotFoundException e) {&lt;br /&gt;
    this.error = FILE_ERROR_NO_FILE; return false;&lt;br /&gt;
  }&lt;br /&gt;
  // ripping the file&lt;br /&gt;
  String str = null;&lt;br /&gt;
  ArrayList allStrings = new ArrayList();&lt;br /&gt;
  try {&lt;br /&gt;
    while (!(str = br.readLine()).equals(null)) { allStrings.add(str); }&lt;br /&gt;
  } &lt;br /&gt;
  catch (IOException e) {&lt;br /&gt;
    this.error = FILE_ERROR_IO_READ; return false;&lt;br /&gt;
  } &lt;br /&gt;
  catch (NullPointerException e) {&lt;br /&gt;
    this.error = FILE_ERROR_END_OF_FILE;&lt;br /&gt;
  }&lt;br /&gt;
  // free the resources&lt;br /&gt;
  try {&lt;br /&gt;
    br.close();&lt;br /&gt;
  } &lt;br /&gt;
  catch (IOException e) {&lt;br /&gt;
    this.error = FILE_ERROR_IO_CLOSE; return false;&lt;br /&gt;
  }&lt;br /&gt;
  this.allStrings = (String[]) allStrings.toArray(new String[0]); &lt;br /&gt;
  return true;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Полный код примера, в том числе код класса ConsoleToFileRipper, применяющий экземпляр класса FileRipper для извлечения данных из файла, можно найти на диске в каталоге '''examples 1'''.&lt;br /&gt;
&lt;br /&gt;
=== Запись данных ===&lt;br /&gt;
Процесс записи данных в файл хоть и отличается от чтения, но тоже достаточно похож на организацию конвейера. Для записи&lt;br /&gt;
я обычно использую связку BufferedWriter, OutputStreamWriter, FileOutputStream.&lt;br /&gt;
&amp;lt;source lang = &amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
BufferedWriter out;&lt;br /&gt;
out = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(pathToFile), encoding));&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Для освобождения ресурсов, которые используют экземпляры классов BufferedReader и BufferedWriter, необходимо вызвать метод&lt;br /&gt;
close().&lt;br /&gt;
&lt;br /&gt;
Далее приведу простой пример метода, который записывает строковый массив в файл (полный код метода расположен на диске в&lt;br /&gt;
директории '''examples 2'''):&lt;br /&gt;
&amp;lt;source lang = &amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
public boolean createCurrentFile(String pathToFile, String[] allStrings, String encoding){&lt;br /&gt;
  try {&lt;br /&gt;
    BufferedWriter out;&lt;br /&gt;
    out = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(pathToFile), encoding));&lt;br /&gt;
    for (int i = 0; i &amp;lt; allStrings.length; i++) {&lt;br /&gt;
      out.write(allStrings[i]); out.write(‘\n’);&lt;br /&gt;
    }&lt;br /&gt;
    out.close();&lt;br /&gt;
  } &lt;br /&gt;
  catch (IOException e) {&lt;br /&gt;
    e.printStackTrace(); &lt;br /&gt;
    return false;&lt;br /&gt;
  }&lt;br /&gt;
  return true;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Свободный доступ ===&lt;br /&gt;
В представленных ранее примерах доступ к данным осуществляется последовательно, что не всегда удобно (хотя в большинстве случаев именно такой доступ и используется). Для осуществления чтения и записи данных из файла в произвольном порядке существует специальный класс RandomAccessFile, экземпляр которого создается следующим образом:&lt;br /&gt;
&amp;lt;source lang = &amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
RandomAccessFile raf = new RandomAccessFile(pathToFile, mode);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
При этом pathToFile — путь до файла, а mode — режим работы. mode может принимать значения: r (только чтение), rw (чтение-запись), rws (чтение-запись с синхронным сохранением содержимого и метаданных), rwd (чтение-запись с синхронным сохранением содержимого файла). К сожалению, кодировку указать нельзя. Огромным преимуществом подхода является то, что с помощью метода getFilePointer() можно узнать текущее месторасположение указателя, а с помощью метода seek() можно передвинуть указатель в необходимое место в файле. Я предпочитаю не использовать данный класс — считайте это личным предубеждением.&lt;br /&gt;
&lt;br /&gt;
=== Протоколирование работы программы ===&lt;br /&gt;
Для контроля и анализа работы приложения существуют методы протоколирования. Популярным инструментом для этих целей в мире&lt;br /&gt;
Java является библиотека Log4j, которая разрабатывается в Apache Software Foundation. Текущую версию можно загрузить с [http://logging.apache.org/[http://logging.apache.org/]].&lt;br /&gt;
&lt;br /&gt;
Для использования библиотеки необходимо создать конфигурационный файл, который описывает, что, куда и как нужно протоколировать. Log4j имеет три базовые составляющие: logger, appender и layout.&lt;br /&gt;
&lt;br /&gt;
layout — это элементы, определяющие вид и содержание записей. Изначально имеется несколько заранее созданных layout-ов, а в случае необходимости можно создать свой собственный.&lt;br /&gt;
&lt;br /&gt;
Appender — это элемент, определяющий местоположение протокола, с его помощью задается тип протоколирования:&lt;br /&gt;
* файловое протоколирование (FileAppender);&lt;br /&gt;
* консольное протоколирование (ConsoleAppender);&lt;br /&gt;
* протоколирование в базы данных (JDBCAppender);&lt;br /&gt;
* протоколирование на SMTP-сервера (SMTPAppender) и др.&lt;br /&gt;
&lt;br /&gt;
Logger — это элемент, который обеспечивает протоколирование какого-либо события. Если обратиться к ранее приведенной аналогии&lt;br /&gt;
ленточного конвейера, logger — это и есть тот самый конвейер, вызывая методы которого, мы формируем протокол работы программы.&lt;br /&gt;
Элемент logger предусматривает следующие уровни протоколирования: DEBUG, INFO, WARN, ERROR, FATAL; уровням соответствуют методы класса org.apache.log4j.Logger: debug; info; warn; error; fatal.&lt;br /&gt;
&lt;br /&gt;
Ниже представлен пример записей для конфигурационного файла нашего приложения, которые нужно сохранить в файл с названием '''log.properties''' (название файла может быть любым).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 log4j.logger.simple=DEBUG, nameLogAppender&lt;br /&gt;
 log4j.appender.nameLogAppender=org.apache.log4j.FileAppender&lt;br /&gt;
 log4j.appender.nameLogAppender.File=nameLogFile.log&lt;br /&gt;
 log4j.appender.nameLogAppender.layout=org.apache.log4j.SimpleLayout&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Первая строка указывает используемый уровень logger (DEBUG) и appender (nameLogAppender). Далее идут настройки appender: указание типа — FileAppender. В третьей строке указываем путь до файла журнала, а в последней — формат записи. Использовать экземпляр класса Logger можно примерно так (пример протоколирования приведен на диске в каталоге '''examples 3'''):&lt;br /&gt;
&amp;lt;source lang = &amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
File propertiesFile = new File(&amp;quot;log.properties&amp;quot;);&lt;br /&gt;
PropertyConfigurator.configure(propertiesFile.toString());&lt;br /&gt;
Logger logger = Logger.getLogger(&amp;quot;simple&amp;quot;);&lt;br /&gt;
logger.info(&amp;quot;the program has started&amp;quot;);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Документы XML ===&lt;br /&gt;
Проектируя и создавая ПО, невозможно не столкнутся с миром XML (Extensible Markup Language). XML был создан в недрах World Wide&lt;br /&gt;
Web Consortium (W3C) для преодоления ограничений языка HTML. Можно сказать, что HTML — один из самых успешных языков, область&lt;br /&gt;
его использования с каждым годом растет (в основном в объемах). Несмотря на это, почему же W3C создал XML, и зачем вам использовать этот язык? В чем ограниченность HTML? Ответ на эти вопросы один:XML был создан для обеспечения взаимодействия разнородных систем.&lt;br /&gt;
&lt;br /&gt;
HTML, как и любой другой текстовый язык, не позволяет перенести смысл тех данных, которые он хранит. XML был разработан для решения этой задачи с прицелом на Web, но получился таким удачным, что его стали использовать практически везде. Суть XML в том, что он хранит семантический смысл данных, поэтому выполнив анализ такого XML-документа, система может «понять» полученные данные. В Интернете существует большое количество информации, посвященной XML (например, [http://www.ibm.com/developerworks/xml/[www.ibm.com/developerworks/xml/]]), поэтому не будем подробно останавливаться на его преимуществах, а сразу приступим к использованию.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang = &amp;quot;xml&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;?xml version=&amp;quot;1.0&amp;quot; ?&amp;gt;&lt;br /&gt;
&amp;lt;line name=&amp;quot;firstLine&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;point id=&amp;quot;1&amp;quot; theX=&amp;quot;1&amp;quot; theY=&amp;quot;1&amp;quot;/&amp;gt;&lt;br /&gt;
&amp;lt;point id=&amp;quot;2&amp;quot; theX=&amp;quot;2&amp;quot; theY=&amp;quot;2&amp;quot;/&amp;gt;&lt;br /&gt;
&amp;lt;/line&amp;gt;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Выше приведен простой пример XML-документа, содержащего корневой элемент line, который, в свою очередь, содержит два узла с&lt;br /&gt;
тремя атрибутами (id, theX, theY) каждый.&lt;br /&gt;
&lt;br /&gt;
=== Создание XML-документа ===&lt;br /&gt;
Говоря про создание XML-документа, я подразумеваю создание дерева XML-документа в памяти системы, то есть объекта DOM (Document Object Model). DOM была создана W3C, и это – официальная Рекомендация консорциума. В противовес DOM существует SAX (Simple API for XML). С моделью SAX можно ознакомиться более подробно в &lt;br /&gt;
[http://www-128.ibm.com/developerworks/ru/views/xml/libraryview.jsp[http://www-128.ibm.com/developerworks/ru/views/xml/libraryview.jsp]]. Основная разница между методами заключается в том, что DOM обеспечивает виртуальное представление XML-файла в памяти системы, в то время как SAX – это событийная модель обработки, в которой в момент встречи определенного элемента вызывается соответствующее событие.&lt;br /&gt;
&lt;br /&gt;
Для создания «отображения» XML-файла в памяти системы необходимо воспользоваться классом Document, экземпляр которого можно получить следующим образом:&lt;br /&gt;
&amp;lt;source lang = &amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();&lt;br /&gt;
DocumentBuilder db = dbf.newDocumentBuilder();&lt;br /&gt;
Document doc = db.newDocument();&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Создание корневого узла XML документа можно выполняется так:&lt;br /&gt;
&amp;lt;source lang = &amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
Element root = doc.createElement(&amp;quot;line&amp;quot;);&lt;br /&gt;
root.setAttribute(&amp;quot;name&amp;quot;, &amp;quot;firstLine&amp;quot;);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
С помощью метода createElement(name) производится создание элементов, в то время как создание и установка значений атрибутов&lt;br /&gt;
элементов производится с помощью метода setAttribute(name, value), где name – имя атрибута, а value – его значение. С помощью метода appendChild можно добавить узел в элемент или произвести запись элемента в документ XML, например, так:&lt;br /&gt;
&amp;lt;source lang = &amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
root.appendChild(item);&lt;br /&gt;
doc.appendChild(root);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Более детально процесс создания XML документа на примере класса Line изложен в директории '''examples 4'''. При вызове метода&lt;br /&gt;
createDoc() этого класса создается экземпляр класса Document, идентичный приведенному ранее коду XML.&lt;br /&gt;
&lt;br /&gt;
=== Сохранение XML-документа ===&lt;br /&gt;
Для сохранения созданного в памяти документа предлагаю воспользоваться методом saveXML(docToSave, pathToFile, charSet). В процессе сохранения участвует уже знакомый нам OutputStreamWriter, а также экземпляр класса Transformer, который обеспечивает преобразование объекта DOMSource в выходной поток.&lt;br /&gt;
&amp;lt;source lang = &amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
public void saveXML(Document docToSave, String pathToFile, String charSet) {&lt;br /&gt;
  try {&lt;br /&gt;
    Writer target = new OutputStreamWriter(new FileOutputStream(pathToFile), charSet);&lt;br /&gt;
    Source source = new DOMSource(docToSave);&lt;br /&gt;
    StreamResult dest = new StreamResult(target);&lt;br /&gt;
    Transformer t = TransformerFactory.newInstance().newTransformer();&lt;br /&gt;
    t.setOutputProperty(OutputKeys.ENCODING, charSet);&lt;br /&gt;
    t.setOutputProperty(OutputKeys.INDENT, “yes”);&lt;br /&gt;
    t.transform(source, dest);  &lt;br /&gt;
    target.flush();&lt;br /&gt;
    target.close();&lt;br /&gt;
  } &lt;br /&gt;
  catch (Exception ex) {&lt;br /&gt;
    ex.printStackTrace();&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Реализация этого метода представлена на диске в директории '''examples 5'''.&lt;br /&gt;
&lt;br /&gt;
=== Загрузка XML-документа ===&lt;br /&gt;
&lt;br /&gt;
=== Извлечение данных из XML-документа ===&lt;/div&gt;</summary>
		<author><name>Skryabin yuri</name></author>	</entry>

	<entry>
		<id>http://wiki.linuxformat.ru/wiki/LXF86:Java</id>
		<title>LXF86:Java</title>
		<link rel="alternate" type="text/html" href="http://wiki.linuxformat.ru/wiki/LXF86:Java"/>
				<updated>2008-03-13T10:28:34Z</updated>
		
		<summary type="html">&lt;p&gt;Skryabin yuri: /* Создание XML-документа */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=== Хранение данных ===&lt;br /&gt;
''ЧАСТЬ 3: Даже самой замечательной программе надо откуда-то черпать данные для своей работы. Данные, как известно, хранятся в файлах. Тему продолжает '''Антон Черноусов'''.''&lt;br /&gt;
&lt;br /&gt;
В предыдущей статье из цикла, посвященного программированию на Java, были рассмотрены вопросы организации простых вычислений, ветвлений, циклов, а также генерации и обработки исключений.&lt;br /&gt;
&lt;br /&gt;
В течение третьего урока мы поговорим о работе с файлами, о протоколировании работы программы и коснемся методов работы с&lt;br /&gt;
XML-данными.&lt;br /&gt;
&lt;br /&gt;
=== Файлы — потоки ===&lt;br /&gt;
Сказочное королевство под руководством царевны Несмеяны (так как cупруг практически всегда отсутствовал), благодаря талантам и приобретенным навыкам, стало разрастаться, и результаты полюдья просто-напросто перестали помещаться в семейный чулан. Чтобы накапливать и хранить богатства, потребовались дополнительные помещения, роль которых для нас привычно играют файлы.&lt;br /&gt;
&lt;br /&gt;
Отношение к файлам в Java достаточно непростое: если рассматривать файл как устройство для ввода/вывода информации — с этой точ&lt;br /&gt;
ки зрения он подобен блоку памяти или экрану, интерфейс доступа к которому унифицирован: это поток. Но несмотря на унифицированный интерфейс, существует большое количество классов сходной функциональности, в которых легко запутаться.&lt;br /&gt;
&lt;br /&gt;
Поток можно представить в виде ленточного конвейера с последовательным размещением или извлечением данных, при использовании&lt;br /&gt;
которого задача программиста сводиться к осуществлению операций «поместить/читать» данные, а остальные детали реализации скрыты&lt;br /&gt;
от него.&lt;br /&gt;
&lt;br /&gt;
=== Чтение данных ===&lt;br /&gt;
Разнообразие классов для работы с файлами позволяет выбрать для себя ту связку, которая больше нравится. Лично я для чтения данных использую BufferedReader, InputStreamReader и FileInputStream. Собственно взаимодействие этих классов для программиста заканчивается в момент создания экземпляра BufferedReader, что делается следующим образом:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang = &amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
BufferedReader br = null;&lt;br /&gt;
br = new BufferedReader(new InputStreamReader(new FileInputStream(pathToFile), encoding));&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
В процессе создания участвуют строковые переменные, содержащие путь к файлу и кодировку, в которой производится считывание&lt;br /&gt;
данных: pathToFile и encoding. В классах, работающих с файлами, считается обязательным создавать переменную для кодировки по умолчанию:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang = &amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
protected static String DEFAULT_ENCODING = &amp;quot;UTF-8&amp;quot;;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Любой текстовый файл можно представить себе в виде набора строк, поэтому давайте реализуем метод для считывания содержимого&lt;br /&gt;
файла в массив String[]. Далее представлен метод rippedCurrentFile(path ToFile, encoding) класса FileRipper, который извлекает данные из файла с помощью метода readLine() экземпляра класса BufferedReader:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang = &amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
protected boolean rippedCurrentFile(String pathToFile, String encoding) {&lt;br /&gt;
  // connecting to file&lt;br /&gt;
  BufferedReader br = null;&lt;br /&gt;
  try {&lt;br /&gt;
    br = new BufferedReader(new InputStreamReader(new FileInputStream(pathToFile),encoding));&lt;br /&gt;
  } &lt;br /&gt;
  catch (UnsupportedEncodingException e) {&lt;br /&gt;
    this.error = FILE_ERROR_UNSUPPORTED_ENCODING; return false;&lt;br /&gt;
  } &lt;br /&gt;
  catch (FileNotFoundException e) {&lt;br /&gt;
    this.error = FILE_ERROR_NO_FILE; return false;&lt;br /&gt;
  }&lt;br /&gt;
  // ripping the file&lt;br /&gt;
  String str = null;&lt;br /&gt;
  ArrayList allStrings = new ArrayList();&lt;br /&gt;
  try {&lt;br /&gt;
    while (!(str = br.readLine()).equals(null)) { allStrings.add(str); }&lt;br /&gt;
  } &lt;br /&gt;
  catch (IOException e) {&lt;br /&gt;
    this.error = FILE_ERROR_IO_READ; return false;&lt;br /&gt;
  } &lt;br /&gt;
  catch (NullPointerException e) {&lt;br /&gt;
    this.error = FILE_ERROR_END_OF_FILE;&lt;br /&gt;
  }&lt;br /&gt;
  // free the resources&lt;br /&gt;
  try {&lt;br /&gt;
    br.close();&lt;br /&gt;
  } &lt;br /&gt;
  catch (IOException e) {&lt;br /&gt;
    this.error = FILE_ERROR_IO_CLOSE; return false;&lt;br /&gt;
  }&lt;br /&gt;
  this.allStrings = (String[]) allStrings.toArray(new String[0]); &lt;br /&gt;
  return true;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Полный код примера, в том числе код класса ConsoleToFileRipper, применяющий экземпляр класса FileRipper для извлечения данных из файла, можно найти на диске в каталоге '''examples 1'''.&lt;br /&gt;
&lt;br /&gt;
=== Запись данных ===&lt;br /&gt;
Процесс записи данных в файл хоть и отличается от чтения, но тоже достаточно похож на организацию конвейера. Для записи&lt;br /&gt;
я обычно использую связку BufferedWriter, OutputStreamWriter, FileOutputStream.&lt;br /&gt;
&amp;lt;source lang = &amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
BufferedWriter out;&lt;br /&gt;
out = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(pathToFile), encoding));&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Для освобождения ресурсов, которые используют экземпляры классов BufferedReader и BufferedWriter, необходимо вызвать метод&lt;br /&gt;
close().&lt;br /&gt;
&lt;br /&gt;
Далее приведу простой пример метода, который записывает строковый массив в файл (полный код метода расположен на диске в&lt;br /&gt;
директории '''examples 2'''):&lt;br /&gt;
&amp;lt;source lang = &amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
public boolean createCurrentFile(String pathToFile, String[] allStrings, String encoding){&lt;br /&gt;
  try {&lt;br /&gt;
    BufferedWriter out;&lt;br /&gt;
    out = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(pathToFile), encoding));&lt;br /&gt;
    for (int i = 0; i &amp;lt; allStrings.length; i++) {&lt;br /&gt;
      out.write(allStrings[i]); out.write(‘\n’);&lt;br /&gt;
    }&lt;br /&gt;
    out.close();&lt;br /&gt;
  } &lt;br /&gt;
  catch (IOException e) {&lt;br /&gt;
    e.printStackTrace(); &lt;br /&gt;
    return false;&lt;br /&gt;
  }&lt;br /&gt;
  return true;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Свободный доступ ===&lt;br /&gt;
В представленных ранее примерах доступ к данным осуществляется последовательно, что не всегда удобно (хотя в большинстве случаев именно такой доступ и используется). Для осуществления чтения и записи данных из файла в произвольном порядке существует специальный класс RandomAccessFile, экземпляр которого создается следующим образом:&lt;br /&gt;
&amp;lt;source lang = &amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
RandomAccessFile raf = new RandomAccessFile(pathToFile, mode);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
При этом pathToFile — путь до файла, а mode — режим работы. mode может принимать значения: r (только чтение), rw (чтение-запись), rws (чтение-запись с синхронным сохранением содержимого и метаданных), rwd (чтение-запись с синхронным сохранением содержимого файла). К сожалению, кодировку указать нельзя. Огромным преимуществом подхода является то, что с помощью метода getFilePointer() можно узнать текущее месторасположение указателя, а с помощью метода seek() можно передвинуть указатель в необходимое место в файле. Я предпочитаю не использовать данный класс — считайте это личным предубеждением.&lt;br /&gt;
&lt;br /&gt;
=== Протоколирование работы программы ===&lt;br /&gt;
Для контроля и анализа работы приложения существуют методы протоколирования. Популярным инструментом для этих целей в мире&lt;br /&gt;
Java является библиотека Log4j, которая разрабатывается в Apache Software Foundation. Текущую версию можно загрузить с [http://logging.apache.org/[http://logging.apache.org/]].&lt;br /&gt;
&lt;br /&gt;
Для использования библиотеки необходимо создать конфигурационный файл, который описывает, что, куда и как нужно протоколировать. Log4j имеет три базовые составляющие: logger, appender и layout.&lt;br /&gt;
&lt;br /&gt;
layout — это элементы, определяющие вид и содержание записей. Изначально имеется несколько заранее созданных layout-ов, а в случае необходимости можно создать свой собственный.&lt;br /&gt;
&lt;br /&gt;
Appender — это элемент, определяющий местоположение протокола, с его помощью задается тип протоколирования:&lt;br /&gt;
* файловое протоколирование (FileAppender);&lt;br /&gt;
* консольное протоколирование (ConsoleAppender);&lt;br /&gt;
* протоколирование в базы данных (JDBCAppender);&lt;br /&gt;
* протоколирование на SMTP-сервера (SMTPAppender) и др.&lt;br /&gt;
&lt;br /&gt;
Logger — это элемент, который обеспечивает протоколирование какого-либо события. Если обратиться к ранее приведенной аналогии&lt;br /&gt;
ленточного конвейера, logger — это и есть тот самый конвейер, вызывая методы которого, мы формируем протокол работы программы.&lt;br /&gt;
Элемент logger предусматривает следующие уровни протоколирования: DEBUG, INFO, WARN, ERROR, FATAL; уровням соответствуют методы класса org.apache.log4j.Logger: debug; info; warn; error; fatal.&lt;br /&gt;
&lt;br /&gt;
Ниже представлен пример записей для конфигурационного файла нашего приложения, которые нужно сохранить в файл с названием '''log.properties''' (название файла может быть любым).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 log4j.logger.simple=DEBUG, nameLogAppender&lt;br /&gt;
 log4j.appender.nameLogAppender=org.apache.log4j.FileAppender&lt;br /&gt;
 log4j.appender.nameLogAppender.File=nameLogFile.log&lt;br /&gt;
 log4j.appender.nameLogAppender.layout=org.apache.log4j.SimpleLayout&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Первая строка указывает используемый уровень logger (DEBUG) и appender (nameLogAppender). Далее идут настройки appender: указание типа — FileAppender. В третьей строке указываем путь до файла журнала, а в последней — формат записи. Использовать экземпляр класса Logger можно примерно так (пример протоколирования приведен на диске в каталоге '''examples 3'''):&lt;br /&gt;
&amp;lt;source lang = &amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
File propertiesFile = new File(&amp;quot;log.properties&amp;quot;);&lt;br /&gt;
PropertyConfigurator.configure(propertiesFile.toString());&lt;br /&gt;
Logger logger = Logger.getLogger(&amp;quot;simple&amp;quot;);&lt;br /&gt;
logger.info(&amp;quot;the program has started&amp;quot;);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Документы XML ===&lt;br /&gt;
Проектируя и создавая ПО, невозможно не столкнутся с миром XML (Extensible Markup Language). XML был создан в недрах World Wide&lt;br /&gt;
Web Consortium (W3C) для преодоления ограничений языка HTML. Можно сказать, что HTML — один из самых успешных языков, область&lt;br /&gt;
его использования с каждым годом растет (в основном в объемах). Несмотря на это, почему же W3C создал XML, и зачем вам использовать этот язык? В чем ограниченность HTML? Ответ на эти вопросы один:XML был создан для обеспечения взаимодействия разнородных систем.&lt;br /&gt;
&lt;br /&gt;
HTML, как и любой другой текстовый язык, не позволяет перенести смысл тех данных, которые он хранит. XML был разработан для решения этой задачи с прицелом на Web, но получился таким удачным, что его стали использовать практически везде. Суть XML в том, что он хранит семантический смысл данных, поэтому выполнив анализ такого XML-документа, система может «понять» полученные данные. В Интернете существует большое количество информации, посвященной XML (например, [http://www.ibm.com/developerworks/xml/[www.ibm.com/developerworks/xml/]]), поэтому не будем подробно останавливаться на его преимуществах, а сразу приступим к использованию.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang = &amp;quot;xml&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;?xml version=&amp;quot;1.0&amp;quot; ?&amp;gt;&lt;br /&gt;
&amp;lt;line name=&amp;quot;firstLine&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;point id=&amp;quot;1&amp;quot; theX=&amp;quot;1&amp;quot; theY=&amp;quot;1&amp;quot;/&amp;gt;&lt;br /&gt;
&amp;lt;point id=&amp;quot;2&amp;quot; theX=&amp;quot;2&amp;quot; theY=&amp;quot;2&amp;quot;/&amp;gt;&lt;br /&gt;
&amp;lt;/line&amp;gt;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Выше приведен простой пример XML-документа, содержащего корневой элемент line, который, в свою очередь, содержит два узла с&lt;br /&gt;
тремя атрибутами (id, theX, theY) каждый.&lt;br /&gt;
&lt;br /&gt;
=== Создание XML-документа ===&lt;br /&gt;
Говоря про создание XML-документа, я подразумеваю создание дерева XML-документа в памяти системы, то есть объекта DOM (Document Object Model). DOM была создана W3C, и это – официальная Рекомендация консорциума. В противовес DOM существует SAX (Simple API for XML). С моделью SAX можно ознакомиться более подробно в &lt;br /&gt;
[http://www-128.ibm.com/developerworks/ru/views/xml/libraryview.jsp[http://www-128.ibm.com/developerworks/ru/views/xml/libraryview.jsp]]. Основная разница между методами заключается в том, что DOM обеспечивает виртуальное представление XML-файла в памяти системы, в то время как SAX – это событийная модель обработки, в которой в момент встречи определенного элемента вызывается соответствующее событие.&lt;br /&gt;
&lt;br /&gt;
Для создания «отображения» XML-файла в памяти системы необходимо воспользоваться классом Document, экземпляр которого можно получить следующим образом:&lt;br /&gt;
&amp;lt;source lang = &amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();&lt;br /&gt;
DocumentBuilder db = dbf.newDocumentBuilder();&lt;br /&gt;
Document doc = db.newDocument();&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Создание корневого узла XML документа можно выполняется так:&lt;br /&gt;
&amp;lt;source lang = &amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
Element root = doc.createElement(&amp;quot;line&amp;quot;);&lt;br /&gt;
root.setAttribute(&amp;quot;name&amp;quot;, &amp;quot;firstLine&amp;quot;);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
С помощью метода createElement(name) производится создание элементов, в то время как создание и установка значений атрибутов&lt;br /&gt;
элементов производится с помощью метода setAttribute(name, value), где name – имя атрибута, а value – его значение. С помощью метода appendChild можно добавить узел в элемент или произвести запись элемента в документ XML, например, так:&lt;br /&gt;
&amp;lt;source lang = &amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
root.appendChild(item);&lt;br /&gt;
doc.appendChild(root);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Более детально процесс создания XML документа на примере класса Line изложен в директории '''examples 4'''. При вызове метода&lt;br /&gt;
createDoc() этого класса создается экземпляр класса Document, идентичный приведенному ранее коду XML.&lt;br /&gt;
&lt;br /&gt;
=== Сохранение XML-документа ===&lt;br /&gt;
&lt;br /&gt;
=== Загрузка XML-документа ===&lt;br /&gt;
&lt;br /&gt;
=== Извлечение данных из XML-документа ===&lt;/div&gt;</summary>
		<author><name>Skryabin yuri</name></author>	</entry>

	<entry>
		<id>http://wiki.linuxformat.ru/wiki/LXF86:Java</id>
		<title>LXF86:Java</title>
		<link rel="alternate" type="text/html" href="http://wiki.linuxformat.ru/wiki/LXF86:Java"/>
				<updated>2008-03-13T10:21:50Z</updated>
		
		<summary type="html">&lt;p&gt;Skryabin yuri: /* Документы XML */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=== Хранение данных ===&lt;br /&gt;
''ЧАСТЬ 3: Даже самой замечательной программе надо откуда-то черпать данные для своей работы. Данные, как известно, хранятся в файлах. Тему продолжает '''Антон Черноусов'''.''&lt;br /&gt;
&lt;br /&gt;
В предыдущей статье из цикла, посвященного программированию на Java, были рассмотрены вопросы организации простых вычислений, ветвлений, циклов, а также генерации и обработки исключений.&lt;br /&gt;
&lt;br /&gt;
В течение третьего урока мы поговорим о работе с файлами, о протоколировании работы программы и коснемся методов работы с&lt;br /&gt;
XML-данными.&lt;br /&gt;
&lt;br /&gt;
=== Файлы — потоки ===&lt;br /&gt;
Сказочное королевство под руководством царевны Несмеяны (так как cупруг практически всегда отсутствовал), благодаря талантам и приобретенным навыкам, стало разрастаться, и результаты полюдья просто-напросто перестали помещаться в семейный чулан. Чтобы накапливать и хранить богатства, потребовались дополнительные помещения, роль которых для нас привычно играют файлы.&lt;br /&gt;
&lt;br /&gt;
Отношение к файлам в Java достаточно непростое: если рассматривать файл как устройство для ввода/вывода информации — с этой точ&lt;br /&gt;
ки зрения он подобен блоку памяти или экрану, интерфейс доступа к которому унифицирован: это поток. Но несмотря на унифицированный интерфейс, существует большое количество классов сходной функциональности, в которых легко запутаться.&lt;br /&gt;
&lt;br /&gt;
Поток можно представить в виде ленточного конвейера с последовательным размещением или извлечением данных, при использовании&lt;br /&gt;
которого задача программиста сводиться к осуществлению операций «поместить/читать» данные, а остальные детали реализации скрыты&lt;br /&gt;
от него.&lt;br /&gt;
&lt;br /&gt;
=== Чтение данных ===&lt;br /&gt;
Разнообразие классов для работы с файлами позволяет выбрать для себя ту связку, которая больше нравится. Лично я для чтения данных использую BufferedReader, InputStreamReader и FileInputStream. Собственно взаимодействие этих классов для программиста заканчивается в момент создания экземпляра BufferedReader, что делается следующим образом:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang = &amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
BufferedReader br = null;&lt;br /&gt;
br = new BufferedReader(new InputStreamReader(new FileInputStream(pathToFile), encoding));&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
В процессе создания участвуют строковые переменные, содержащие путь к файлу и кодировку, в которой производится считывание&lt;br /&gt;
данных: pathToFile и encoding. В классах, работающих с файлами, считается обязательным создавать переменную для кодировки по умолчанию:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang = &amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
protected static String DEFAULT_ENCODING = &amp;quot;UTF-8&amp;quot;;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Любой текстовый файл можно представить себе в виде набора строк, поэтому давайте реализуем метод для считывания содержимого&lt;br /&gt;
файла в массив String[]. Далее представлен метод rippedCurrentFile(path ToFile, encoding) класса FileRipper, который извлекает данные из файла с помощью метода readLine() экземпляра класса BufferedReader:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang = &amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
protected boolean rippedCurrentFile(String pathToFile, String encoding) {&lt;br /&gt;
  // connecting to file&lt;br /&gt;
  BufferedReader br = null;&lt;br /&gt;
  try {&lt;br /&gt;
    br = new BufferedReader(new InputStreamReader(new FileInputStream(pathToFile),encoding));&lt;br /&gt;
  } &lt;br /&gt;
  catch (UnsupportedEncodingException e) {&lt;br /&gt;
    this.error = FILE_ERROR_UNSUPPORTED_ENCODING; return false;&lt;br /&gt;
  } &lt;br /&gt;
  catch (FileNotFoundException e) {&lt;br /&gt;
    this.error = FILE_ERROR_NO_FILE; return false;&lt;br /&gt;
  }&lt;br /&gt;
  // ripping the file&lt;br /&gt;
  String str = null;&lt;br /&gt;
  ArrayList allStrings = new ArrayList();&lt;br /&gt;
  try {&lt;br /&gt;
    while (!(str = br.readLine()).equals(null)) { allStrings.add(str); }&lt;br /&gt;
  } &lt;br /&gt;
  catch (IOException e) {&lt;br /&gt;
    this.error = FILE_ERROR_IO_READ; return false;&lt;br /&gt;
  } &lt;br /&gt;
  catch (NullPointerException e) {&lt;br /&gt;
    this.error = FILE_ERROR_END_OF_FILE;&lt;br /&gt;
  }&lt;br /&gt;
  // free the resources&lt;br /&gt;
  try {&lt;br /&gt;
    br.close();&lt;br /&gt;
  } &lt;br /&gt;
  catch (IOException e) {&lt;br /&gt;
    this.error = FILE_ERROR_IO_CLOSE; return false;&lt;br /&gt;
  }&lt;br /&gt;
  this.allStrings = (String[]) allStrings.toArray(new String[0]); &lt;br /&gt;
  return true;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Полный код примера, в том числе код класса ConsoleToFileRipper, применяющий экземпляр класса FileRipper для извлечения данных из файла, можно найти на диске в каталоге '''examples 1'''.&lt;br /&gt;
&lt;br /&gt;
=== Запись данных ===&lt;br /&gt;
Процесс записи данных в файл хоть и отличается от чтения, но тоже достаточно похож на организацию конвейера. Для записи&lt;br /&gt;
я обычно использую связку BufferedWriter, OutputStreamWriter, FileOutputStream.&lt;br /&gt;
&amp;lt;source lang = &amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
BufferedWriter out;&lt;br /&gt;
out = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(pathToFile), encoding));&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Для освобождения ресурсов, которые используют экземпляры классов BufferedReader и BufferedWriter, необходимо вызвать метод&lt;br /&gt;
close().&lt;br /&gt;
&lt;br /&gt;
Далее приведу простой пример метода, который записывает строковый массив в файл (полный код метода расположен на диске в&lt;br /&gt;
директории '''examples 2'''):&lt;br /&gt;
&amp;lt;source lang = &amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
public boolean createCurrentFile(String pathToFile, String[] allStrings, String encoding){&lt;br /&gt;
  try {&lt;br /&gt;
    BufferedWriter out;&lt;br /&gt;
    out = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(pathToFile), encoding));&lt;br /&gt;
    for (int i = 0; i &amp;lt; allStrings.length; i++) {&lt;br /&gt;
      out.write(allStrings[i]); out.write(‘\n’);&lt;br /&gt;
    }&lt;br /&gt;
    out.close();&lt;br /&gt;
  } &lt;br /&gt;
  catch (IOException e) {&lt;br /&gt;
    e.printStackTrace(); &lt;br /&gt;
    return false;&lt;br /&gt;
  }&lt;br /&gt;
  return true;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Свободный доступ ===&lt;br /&gt;
В представленных ранее примерах доступ к данным осуществляется последовательно, что не всегда удобно (хотя в большинстве случаев именно такой доступ и используется). Для осуществления чтения и записи данных из файла в произвольном порядке существует специальный класс RandomAccessFile, экземпляр которого создается следующим образом:&lt;br /&gt;
&amp;lt;source lang = &amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
RandomAccessFile raf = new RandomAccessFile(pathToFile, mode);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
При этом pathToFile — путь до файла, а mode — режим работы. mode может принимать значения: r (только чтение), rw (чтение-запись), rws (чтение-запись с синхронным сохранением содержимого и метаданных), rwd (чтение-запись с синхронным сохранением содержимого файла). К сожалению, кодировку указать нельзя. Огромным преимуществом подхода является то, что с помощью метода getFilePointer() можно узнать текущее месторасположение указателя, а с помощью метода seek() можно передвинуть указатель в необходимое место в файле. Я предпочитаю не использовать данный класс — считайте это личным предубеждением.&lt;br /&gt;
&lt;br /&gt;
=== Протоколирование работы программы ===&lt;br /&gt;
Для контроля и анализа работы приложения существуют методы протоколирования. Популярным инструментом для этих целей в мире&lt;br /&gt;
Java является библиотека Log4j, которая разрабатывается в Apache Software Foundation. Текущую версию можно загрузить с [http://logging.apache.org/[http://logging.apache.org/]].&lt;br /&gt;
&lt;br /&gt;
Для использования библиотеки необходимо создать конфигурационный файл, который описывает, что, куда и как нужно протоколировать. Log4j имеет три базовые составляющие: logger, appender и layout.&lt;br /&gt;
&lt;br /&gt;
layout — это элементы, определяющие вид и содержание записей. Изначально имеется несколько заранее созданных layout-ов, а в случае необходимости можно создать свой собственный.&lt;br /&gt;
&lt;br /&gt;
Appender — это элемент, определяющий местоположение протокола, с его помощью задается тип протоколирования:&lt;br /&gt;
* файловое протоколирование (FileAppender);&lt;br /&gt;
* консольное протоколирование (ConsoleAppender);&lt;br /&gt;
* протоколирование в базы данных (JDBCAppender);&lt;br /&gt;
* протоколирование на SMTP-сервера (SMTPAppender) и др.&lt;br /&gt;
&lt;br /&gt;
Logger — это элемент, который обеспечивает протоколирование какого-либо события. Если обратиться к ранее приведенной аналогии&lt;br /&gt;
ленточного конвейера, logger — это и есть тот самый конвейер, вызывая методы которого, мы формируем протокол работы программы.&lt;br /&gt;
Элемент logger предусматривает следующие уровни протоколирования: DEBUG, INFO, WARN, ERROR, FATAL; уровням соответствуют методы класса org.apache.log4j.Logger: debug; info; warn; error; fatal.&lt;br /&gt;
&lt;br /&gt;
Ниже представлен пример записей для конфигурационного файла нашего приложения, которые нужно сохранить в файл с названием '''log.properties''' (название файла может быть любым).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 log4j.logger.simple=DEBUG, nameLogAppender&lt;br /&gt;
 log4j.appender.nameLogAppender=org.apache.log4j.FileAppender&lt;br /&gt;
 log4j.appender.nameLogAppender.File=nameLogFile.log&lt;br /&gt;
 log4j.appender.nameLogAppender.layout=org.apache.log4j.SimpleLayout&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Первая строка указывает используемый уровень logger (DEBUG) и appender (nameLogAppender). Далее идут настройки appender: указание типа — FileAppender. В третьей строке указываем путь до файла журнала, а в последней — формат записи. Использовать экземпляр класса Logger можно примерно так (пример протоколирования приведен на диске в каталоге '''examples 3'''):&lt;br /&gt;
&amp;lt;source lang = &amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
File propertiesFile = new File(&amp;quot;log.properties&amp;quot;);&lt;br /&gt;
PropertyConfigurator.configure(propertiesFile.toString());&lt;br /&gt;
Logger logger = Logger.getLogger(&amp;quot;simple&amp;quot;);&lt;br /&gt;
logger.info(&amp;quot;the program has started&amp;quot;);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Документы XML ===&lt;br /&gt;
Проектируя и создавая ПО, невозможно не столкнутся с миром XML (Extensible Markup Language). XML был создан в недрах World Wide&lt;br /&gt;
Web Consortium (W3C) для преодоления ограничений языка HTML. Можно сказать, что HTML — один из самых успешных языков, область&lt;br /&gt;
его использования с каждым годом растет (в основном в объемах). Несмотря на это, почему же W3C создал XML, и зачем вам использовать этот язык? В чем ограниченность HTML? Ответ на эти вопросы один:XML был создан для обеспечения взаимодействия разнородных систем.&lt;br /&gt;
&lt;br /&gt;
HTML, как и любой другой текстовый язык, не позволяет перенести смысл тех данных, которые он хранит. XML был разработан для решения этой задачи с прицелом на Web, но получился таким удачным, что его стали использовать практически везде. Суть XML в том, что он хранит семантический смысл данных, поэтому выполнив анализ такого XML-документа, система может «понять» полученные данные. В Интернете существует большое количество информации, посвященной XML (например, [http://www.ibm.com/developerworks/xml/[www.ibm.com/developerworks/xml/]]), поэтому не будем подробно останавливаться на его преимуществах, а сразу приступим к использованию.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang = &amp;quot;xml&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;?xml version=&amp;quot;1.0&amp;quot; ?&amp;gt;&lt;br /&gt;
&amp;lt;line name=&amp;quot;firstLine&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;point id=&amp;quot;1&amp;quot; theX=&amp;quot;1&amp;quot; theY=&amp;quot;1&amp;quot;/&amp;gt;&lt;br /&gt;
&amp;lt;point id=&amp;quot;2&amp;quot; theX=&amp;quot;2&amp;quot; theY=&amp;quot;2&amp;quot;/&amp;gt;&lt;br /&gt;
&amp;lt;/line&amp;gt;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Выше приведен простой пример XML-документа, содержащего корневой элемент line, который, в свою очередь, содержит два узла с&lt;br /&gt;
тремя атрибутами (id, theX, theY) каждый.&lt;br /&gt;
&lt;br /&gt;
=== Создание XML-документа ===&lt;br /&gt;
&lt;br /&gt;
=== Сохранение XML-документа ===&lt;br /&gt;
&lt;br /&gt;
=== Загрузка XML-документа ===&lt;br /&gt;
&lt;br /&gt;
=== Извлечение данных из XML-документа ===&lt;/div&gt;</summary>
		<author><name>Skryabin yuri</name></author>	</entry>

	<entry>
		<id>http://wiki.linuxformat.ru/wiki/LXF86:Java</id>
		<title>LXF86:Java</title>
		<link rel="alternate" type="text/html" href="http://wiki.linuxformat.ru/wiki/LXF86:Java"/>
				<updated>2008-03-13T10:20:01Z</updated>
		
		<summary type="html">&lt;p&gt;Skryabin yuri: /* Документы XML */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=== Хранение данных ===&lt;br /&gt;
''ЧАСТЬ 3: Даже самой замечательной программе надо откуда-то черпать данные для своей работы. Данные, как известно, хранятся в файлах. Тему продолжает '''Антон Черноусов'''.''&lt;br /&gt;
&lt;br /&gt;
В предыдущей статье из цикла, посвященного программированию на Java, были рассмотрены вопросы организации простых вычислений, ветвлений, циклов, а также генерации и обработки исключений.&lt;br /&gt;
&lt;br /&gt;
В течение третьего урока мы поговорим о работе с файлами, о протоколировании работы программы и коснемся методов работы с&lt;br /&gt;
XML-данными.&lt;br /&gt;
&lt;br /&gt;
=== Файлы — потоки ===&lt;br /&gt;
Сказочное королевство под руководством царевны Несмеяны (так как cупруг практически всегда отсутствовал), благодаря талантам и приобретенным навыкам, стало разрастаться, и результаты полюдья просто-напросто перестали помещаться в семейный чулан. Чтобы накапливать и хранить богатства, потребовались дополнительные помещения, роль которых для нас привычно играют файлы.&lt;br /&gt;
&lt;br /&gt;
Отношение к файлам в Java достаточно непростое: если рассматривать файл как устройство для ввода/вывода информации — с этой точ&lt;br /&gt;
ки зрения он подобен блоку памяти или экрану, интерфейс доступа к которому унифицирован: это поток. Но несмотря на унифицированный интерфейс, существует большое количество классов сходной функциональности, в которых легко запутаться.&lt;br /&gt;
&lt;br /&gt;
Поток можно представить в виде ленточного конвейера с последовательным размещением или извлечением данных, при использовании&lt;br /&gt;
которого задача программиста сводиться к осуществлению операций «поместить/читать» данные, а остальные детали реализации скрыты&lt;br /&gt;
от него.&lt;br /&gt;
&lt;br /&gt;
=== Чтение данных ===&lt;br /&gt;
Разнообразие классов для работы с файлами позволяет выбрать для себя ту связку, которая больше нравится. Лично я для чтения данных использую BufferedReader, InputStreamReader и FileInputStream. Собственно взаимодействие этих классов для программиста заканчивается в момент создания экземпляра BufferedReader, что делается следующим образом:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang = &amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
BufferedReader br = null;&lt;br /&gt;
br = new BufferedReader(new InputStreamReader(new FileInputStream(pathToFile), encoding));&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
В процессе создания участвуют строковые переменные, содержащие путь к файлу и кодировку, в которой производится считывание&lt;br /&gt;
данных: pathToFile и encoding. В классах, работающих с файлами, считается обязательным создавать переменную для кодировки по умолчанию:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang = &amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
protected static String DEFAULT_ENCODING = &amp;quot;UTF-8&amp;quot;;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Любой текстовый файл можно представить себе в виде набора строк, поэтому давайте реализуем метод для считывания содержимого&lt;br /&gt;
файла в массив String[]. Далее представлен метод rippedCurrentFile(path ToFile, encoding) класса FileRipper, который извлекает данные из файла с помощью метода readLine() экземпляра класса BufferedReader:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang = &amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
protected boolean rippedCurrentFile(String pathToFile, String encoding) {&lt;br /&gt;
  // connecting to file&lt;br /&gt;
  BufferedReader br = null;&lt;br /&gt;
  try {&lt;br /&gt;
    br = new BufferedReader(new InputStreamReader(new FileInputStream(pathToFile),encoding));&lt;br /&gt;
  } &lt;br /&gt;
  catch (UnsupportedEncodingException e) {&lt;br /&gt;
    this.error = FILE_ERROR_UNSUPPORTED_ENCODING; return false;&lt;br /&gt;
  } &lt;br /&gt;
  catch (FileNotFoundException e) {&lt;br /&gt;
    this.error = FILE_ERROR_NO_FILE; return false;&lt;br /&gt;
  }&lt;br /&gt;
  // ripping the file&lt;br /&gt;
  String str = null;&lt;br /&gt;
  ArrayList allStrings = new ArrayList();&lt;br /&gt;
  try {&lt;br /&gt;
    while (!(str = br.readLine()).equals(null)) { allStrings.add(str); }&lt;br /&gt;
  } &lt;br /&gt;
  catch (IOException e) {&lt;br /&gt;
    this.error = FILE_ERROR_IO_READ; return false;&lt;br /&gt;
  } &lt;br /&gt;
  catch (NullPointerException e) {&lt;br /&gt;
    this.error = FILE_ERROR_END_OF_FILE;&lt;br /&gt;
  }&lt;br /&gt;
  // free the resources&lt;br /&gt;
  try {&lt;br /&gt;
    br.close();&lt;br /&gt;
  } &lt;br /&gt;
  catch (IOException e) {&lt;br /&gt;
    this.error = FILE_ERROR_IO_CLOSE; return false;&lt;br /&gt;
  }&lt;br /&gt;
  this.allStrings = (String[]) allStrings.toArray(new String[0]); &lt;br /&gt;
  return true;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Полный код примера, в том числе код класса ConsoleToFileRipper, применяющий экземпляр класса FileRipper для извлечения данных из файла, можно найти на диске в каталоге '''examples 1'''.&lt;br /&gt;
&lt;br /&gt;
=== Запись данных ===&lt;br /&gt;
Процесс записи данных в файл хоть и отличается от чтения, но тоже достаточно похож на организацию конвейера. Для записи&lt;br /&gt;
я обычно использую связку BufferedWriter, OutputStreamWriter, FileOutputStream.&lt;br /&gt;
&amp;lt;source lang = &amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
BufferedWriter out;&lt;br /&gt;
out = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(pathToFile), encoding));&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Для освобождения ресурсов, которые используют экземпляры классов BufferedReader и BufferedWriter, необходимо вызвать метод&lt;br /&gt;
close().&lt;br /&gt;
&lt;br /&gt;
Далее приведу простой пример метода, который записывает строковый массив в файл (полный код метода расположен на диске в&lt;br /&gt;
директории '''examples 2'''):&lt;br /&gt;
&amp;lt;source lang = &amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
public boolean createCurrentFile(String pathToFile, String[] allStrings, String encoding){&lt;br /&gt;
  try {&lt;br /&gt;
    BufferedWriter out;&lt;br /&gt;
    out = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(pathToFile), encoding));&lt;br /&gt;
    for (int i = 0; i &amp;lt; allStrings.length; i++) {&lt;br /&gt;
      out.write(allStrings[i]); out.write(‘\n’);&lt;br /&gt;
    }&lt;br /&gt;
    out.close();&lt;br /&gt;
  } &lt;br /&gt;
  catch (IOException e) {&lt;br /&gt;
    e.printStackTrace(); &lt;br /&gt;
    return false;&lt;br /&gt;
  }&lt;br /&gt;
  return true;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Свободный доступ ===&lt;br /&gt;
В представленных ранее примерах доступ к данным осуществляется последовательно, что не всегда удобно (хотя в большинстве случаев именно такой доступ и используется). Для осуществления чтения и записи данных из файла в произвольном порядке существует специальный класс RandomAccessFile, экземпляр которого создается следующим образом:&lt;br /&gt;
&amp;lt;source lang = &amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
RandomAccessFile raf = new RandomAccessFile(pathToFile, mode);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
При этом pathToFile — путь до файла, а mode — режим работы. mode может принимать значения: r (только чтение), rw (чтение-запись), rws (чтение-запись с синхронным сохранением содержимого и метаданных), rwd (чтение-запись с синхронным сохранением содержимого файла). К сожалению, кодировку указать нельзя. Огромным преимуществом подхода является то, что с помощью метода getFilePointer() можно узнать текущее месторасположение указателя, а с помощью метода seek() можно передвинуть указатель в необходимое место в файле. Я предпочитаю не использовать данный класс — считайте это личным предубеждением.&lt;br /&gt;
&lt;br /&gt;
=== Протоколирование работы программы ===&lt;br /&gt;
Для контроля и анализа работы приложения существуют методы протоколирования. Популярным инструментом для этих целей в мире&lt;br /&gt;
Java является библиотека Log4j, которая разрабатывается в Apache Software Foundation. Текущую версию можно загрузить с [http://logging.apache.org/[http://logging.apache.org/]].&lt;br /&gt;
&lt;br /&gt;
Для использования библиотеки необходимо создать конфигурационный файл, который описывает, что, куда и как нужно протоколировать. Log4j имеет три базовые составляющие: logger, appender и layout.&lt;br /&gt;
&lt;br /&gt;
layout — это элементы, определяющие вид и содержание записей. Изначально имеется несколько заранее созданных layout-ов, а в случае необходимости можно создать свой собственный.&lt;br /&gt;
&lt;br /&gt;
Appender — это элемент, определяющий местоположение протокола, с его помощью задается тип протоколирования:&lt;br /&gt;
* файловое протоколирование (FileAppender);&lt;br /&gt;
* консольное протоколирование (ConsoleAppender);&lt;br /&gt;
* протоколирование в базы данных (JDBCAppender);&lt;br /&gt;
* протоколирование на SMTP-сервера (SMTPAppender) и др.&lt;br /&gt;
&lt;br /&gt;
Logger — это элемент, который обеспечивает протоколирование какого-либо события. Если обратиться к ранее приведенной аналогии&lt;br /&gt;
ленточного конвейера, logger — это и есть тот самый конвейер, вызывая методы которого, мы формируем протокол работы программы.&lt;br /&gt;
Элемент logger предусматривает следующие уровни протоколирования: DEBUG, INFO, WARN, ERROR, FATAL; уровням соответствуют методы класса org.apache.log4j.Logger: debug; info; warn; error; fatal.&lt;br /&gt;
&lt;br /&gt;
Ниже представлен пример записей для конфигурационного файла нашего приложения, которые нужно сохранить в файл с названием '''log.properties''' (название файла может быть любым).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 log4j.logger.simple=DEBUG, nameLogAppender&lt;br /&gt;
 log4j.appender.nameLogAppender=org.apache.log4j.FileAppender&lt;br /&gt;
 log4j.appender.nameLogAppender.File=nameLogFile.log&lt;br /&gt;
 log4j.appender.nameLogAppender.layout=org.apache.log4j.SimpleLayout&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Первая строка указывает используемый уровень logger (DEBUG) и appender (nameLogAppender). Далее идут настройки appender: указание типа — FileAppender. В третьей строке указываем путь до файла журнала, а в последней — формат записи. Использовать экземпляр класса Logger можно примерно так (пример протоколирования приведен на диске в каталоге '''examples 3'''):&lt;br /&gt;
&amp;lt;source lang = &amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
File propertiesFile = new File(&amp;quot;log.properties&amp;quot;);&lt;br /&gt;
PropertyConfigurator.configure(propertiesFile.toString());&lt;br /&gt;
Logger logger = Logger.getLogger(&amp;quot;simple&amp;quot;);&lt;br /&gt;
logger.info(&amp;quot;the program has started&amp;quot;);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Документы XML ===&lt;br /&gt;
Проектируя и создавая ПО, невозможно не столкнутся с миром XML (Extensible Markup Language). XML был создан в недрах World Wide&lt;br /&gt;
Web Consortium (W3C) для преодоления ограничений языка HTML. Можно сказать, что HTML — один из самых успешных языков, область&lt;br /&gt;
его использования с каждым годом растет (в основном в объемах). Несмотря на это, почему же W3C создал XML, и зачем вам использовать этот язык? В чем ограниченность HTML? Ответ на эти вопросы один:XML был создан для обеспечения взаимодействия разнородных систем.&lt;br /&gt;
&lt;br /&gt;
HTML, как и любой другой текстовый язык, не позволяет перенести смысл тех данных, которые он хранит. XML был разработан для решения этой задачи с прицелом на Web, но получился таким удачным, что его стали использовать практически везде. Суть XML в том, что он хранит семантический смысл данных, поэтому выполнив анализ такого XML-документа, система может «понять» полученные данные. В Интернете существует большое количество информации, посвященной XML (например, [http://www.ibm.com/developerworks/xml[www.ibm.com/developerworks/xml]]), поэтому не будем подробно останавливаться на его преимуществах, а сразу приступим к использованию.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang = &amp;quot;xml&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;?xml version=”1.0” ?&amp;gt;&lt;br /&gt;
&amp;lt;line name=”firstLine”&amp;gt;&lt;br /&gt;
&amp;lt;point id=”1” theX=”1” theY=”1”/&amp;gt;&lt;br /&gt;
&amp;lt;point id=”2” theX=”2” theY=”2”/&amp;gt;&lt;br /&gt;
&amp;lt;/line&amp;gt;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Выше приведен простой пример XML-документа, содержащего корневой элемент line, который, в свою очередь, содержит два узла с&lt;br /&gt;
тремя атрибутами (id, theX, theY) каждый.&lt;br /&gt;
&lt;br /&gt;
=== Создание XML-документа ===&lt;br /&gt;
&lt;br /&gt;
=== Сохранение XML-документа ===&lt;br /&gt;
&lt;br /&gt;
=== Загрузка XML-документа ===&lt;br /&gt;
&lt;br /&gt;
=== Извлечение данных из XML-документа ===&lt;/div&gt;</summary>
		<author><name>Skryabin yuri</name></author>	</entry>

	<entry>
		<id>http://wiki.linuxformat.ru/wiki/LXF86:Java</id>
		<title>LXF86:Java</title>
		<link rel="alternate" type="text/html" href="http://wiki.linuxformat.ru/wiki/LXF86:Java"/>
				<updated>2008-03-13T10:11:55Z</updated>
		
		<summary type="html">&lt;p&gt;Skryabin yuri: /* Протоколирование работы программы */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=== Хранение данных ===&lt;br /&gt;
''ЧАСТЬ 3: Даже самой замечательной программе надо откуда-то черпать данные для своей работы. Данные, как известно, хранятся в файлах. Тему продолжает '''Антон Черноусов'''.''&lt;br /&gt;
&lt;br /&gt;
В предыдущей статье из цикла, посвященного программированию на Java, были рассмотрены вопросы организации простых вычислений, ветвлений, циклов, а также генерации и обработки исключений.&lt;br /&gt;
&lt;br /&gt;
В течение третьего урока мы поговорим о работе с файлами, о протоколировании работы программы и коснемся методов работы с&lt;br /&gt;
XML-данными.&lt;br /&gt;
&lt;br /&gt;
=== Файлы — потоки ===&lt;br /&gt;
Сказочное королевство под руководством царевны Несмеяны (так как cупруг практически всегда отсутствовал), благодаря талантам и приобретенным навыкам, стало разрастаться, и результаты полюдья просто-напросто перестали помещаться в семейный чулан. Чтобы накапливать и хранить богатства, потребовались дополнительные помещения, роль которых для нас привычно играют файлы.&lt;br /&gt;
&lt;br /&gt;
Отношение к файлам в Java достаточно непростое: если рассматривать файл как устройство для ввода/вывода информации — с этой точ&lt;br /&gt;
ки зрения он подобен блоку памяти или экрану, интерфейс доступа к которому унифицирован: это поток. Но несмотря на унифицированный интерфейс, существует большое количество классов сходной функциональности, в которых легко запутаться.&lt;br /&gt;
&lt;br /&gt;
Поток можно представить в виде ленточного конвейера с последовательным размещением или извлечением данных, при использовании&lt;br /&gt;
которого задача программиста сводиться к осуществлению операций «поместить/читать» данные, а остальные детали реализации скрыты&lt;br /&gt;
от него.&lt;br /&gt;
&lt;br /&gt;
=== Чтение данных ===&lt;br /&gt;
Разнообразие классов для работы с файлами позволяет выбрать для себя ту связку, которая больше нравится. Лично я для чтения данных использую BufferedReader, InputStreamReader и FileInputStream. Собственно взаимодействие этих классов для программиста заканчивается в момент создания экземпляра BufferedReader, что делается следующим образом:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang = &amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
BufferedReader br = null;&lt;br /&gt;
br = new BufferedReader(new InputStreamReader(new FileInputStream(pathToFile), encoding));&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
В процессе создания участвуют строковые переменные, содержащие путь к файлу и кодировку, в которой производится считывание&lt;br /&gt;
данных: pathToFile и encoding. В классах, работающих с файлами, считается обязательным создавать переменную для кодировки по умолчанию:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang = &amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
protected static String DEFAULT_ENCODING = &amp;quot;UTF-8&amp;quot;;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Любой текстовый файл можно представить себе в виде набора строк, поэтому давайте реализуем метод для считывания содержимого&lt;br /&gt;
файла в массив String[]. Далее представлен метод rippedCurrentFile(path ToFile, encoding) класса FileRipper, который извлекает данные из файла с помощью метода readLine() экземпляра класса BufferedReader:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang = &amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
protected boolean rippedCurrentFile(String pathToFile, String encoding) {&lt;br /&gt;
  // connecting to file&lt;br /&gt;
  BufferedReader br = null;&lt;br /&gt;
  try {&lt;br /&gt;
    br = new BufferedReader(new InputStreamReader(new FileInputStream(pathToFile),encoding));&lt;br /&gt;
  } &lt;br /&gt;
  catch (UnsupportedEncodingException e) {&lt;br /&gt;
    this.error = FILE_ERROR_UNSUPPORTED_ENCODING; return false;&lt;br /&gt;
  } &lt;br /&gt;
  catch (FileNotFoundException e) {&lt;br /&gt;
    this.error = FILE_ERROR_NO_FILE; return false;&lt;br /&gt;
  }&lt;br /&gt;
  // ripping the file&lt;br /&gt;
  String str = null;&lt;br /&gt;
  ArrayList allStrings = new ArrayList();&lt;br /&gt;
  try {&lt;br /&gt;
    while (!(str = br.readLine()).equals(null)) { allStrings.add(str); }&lt;br /&gt;
  } &lt;br /&gt;
  catch (IOException e) {&lt;br /&gt;
    this.error = FILE_ERROR_IO_READ; return false;&lt;br /&gt;
  } &lt;br /&gt;
  catch (NullPointerException e) {&lt;br /&gt;
    this.error = FILE_ERROR_END_OF_FILE;&lt;br /&gt;
  }&lt;br /&gt;
  // free the resources&lt;br /&gt;
  try {&lt;br /&gt;
    br.close();&lt;br /&gt;
  } &lt;br /&gt;
  catch (IOException e) {&lt;br /&gt;
    this.error = FILE_ERROR_IO_CLOSE; return false;&lt;br /&gt;
  }&lt;br /&gt;
  this.allStrings = (String[]) allStrings.toArray(new String[0]); &lt;br /&gt;
  return true;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Полный код примера, в том числе код класса ConsoleToFileRipper, применяющий экземпляр класса FileRipper для извлечения данных из файла, можно найти на диске в каталоге '''examples 1'''.&lt;br /&gt;
&lt;br /&gt;
=== Запись данных ===&lt;br /&gt;
Процесс записи данных в файл хоть и отличается от чтения, но тоже достаточно похож на организацию конвейера. Для записи&lt;br /&gt;
я обычно использую связку BufferedWriter, OutputStreamWriter, FileOutputStream.&lt;br /&gt;
&amp;lt;source lang = &amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
BufferedWriter out;&lt;br /&gt;
out = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(pathToFile), encoding));&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Для освобождения ресурсов, которые используют экземпляры классов BufferedReader и BufferedWriter, необходимо вызвать метод&lt;br /&gt;
close().&lt;br /&gt;
&lt;br /&gt;
Далее приведу простой пример метода, который записывает строковый массив в файл (полный код метода расположен на диске в&lt;br /&gt;
директории '''examples 2'''):&lt;br /&gt;
&amp;lt;source lang = &amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
public boolean createCurrentFile(String pathToFile, String[] allStrings, String encoding){&lt;br /&gt;
  try {&lt;br /&gt;
    BufferedWriter out;&lt;br /&gt;
    out = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(pathToFile), encoding));&lt;br /&gt;
    for (int i = 0; i &amp;lt; allStrings.length; i++) {&lt;br /&gt;
      out.write(allStrings[i]); out.write(‘\n’);&lt;br /&gt;
    }&lt;br /&gt;
    out.close();&lt;br /&gt;
  } &lt;br /&gt;
  catch (IOException e) {&lt;br /&gt;
    e.printStackTrace(); &lt;br /&gt;
    return false;&lt;br /&gt;
  }&lt;br /&gt;
  return true;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Свободный доступ ===&lt;br /&gt;
В представленных ранее примерах доступ к данным осуществляется последовательно, что не всегда удобно (хотя в большинстве случаев именно такой доступ и используется). Для осуществления чтения и записи данных из файла в произвольном порядке существует специальный класс RandomAccessFile, экземпляр которого создается следующим образом:&lt;br /&gt;
&amp;lt;source lang = &amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
RandomAccessFile raf = new RandomAccessFile(pathToFile, mode);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
При этом pathToFile — путь до файла, а mode — режим работы. mode может принимать значения: r (только чтение), rw (чтение-запись), rws (чтение-запись с синхронным сохранением содержимого и метаданных), rwd (чтение-запись с синхронным сохранением содержимого файла). К сожалению, кодировку указать нельзя. Огромным преимуществом подхода является то, что с помощью метода getFilePointer() можно узнать текущее месторасположение указателя, а с помощью метода seek() можно передвинуть указатель в необходимое место в файле. Я предпочитаю не использовать данный класс — считайте это личным предубеждением.&lt;br /&gt;
&lt;br /&gt;
=== Протоколирование работы программы ===&lt;br /&gt;
Для контроля и анализа работы приложения существуют методы протоколирования. Популярным инструментом для этих целей в мире&lt;br /&gt;
Java является библиотека Log4j, которая разрабатывается в Apache Software Foundation. Текущую версию можно загрузить с [http://logging.apache.org/[http://logging.apache.org/]].&lt;br /&gt;
&lt;br /&gt;
Для использования библиотеки необходимо создать конфигурационный файл, который описывает, что, куда и как нужно протоколировать. Log4j имеет три базовые составляющие: logger, appender и layout.&lt;br /&gt;
&lt;br /&gt;
layout — это элементы, определяющие вид и содержание записей. Изначально имеется несколько заранее созданных layout-ов, а в случае необходимости можно создать свой собственный.&lt;br /&gt;
&lt;br /&gt;
Appender — это элемент, определяющий местоположение протокола, с его помощью задается тип протоколирования:&lt;br /&gt;
* файловое протоколирование (FileAppender);&lt;br /&gt;
* консольное протоколирование (ConsoleAppender);&lt;br /&gt;
* протоколирование в базы данных (JDBCAppender);&lt;br /&gt;
* протоколирование на SMTP-сервера (SMTPAppender) и др.&lt;br /&gt;
&lt;br /&gt;
Logger — это элемент, который обеспечивает протоколирование какого-либо события. Если обратиться к ранее приведенной аналогии&lt;br /&gt;
ленточного конвейера, logger — это и есть тот самый конвейер, вызывая методы которого, мы формируем протокол работы программы.&lt;br /&gt;
Элемент logger предусматривает следующие уровни протоколирования: DEBUG, INFO, WARN, ERROR, FATAL; уровням соответствуют методы класса org.apache.log4j.Logger: debug; info; warn; error; fatal.&lt;br /&gt;
&lt;br /&gt;
Ниже представлен пример записей для конфигурационного файла нашего приложения, которые нужно сохранить в файл с названием '''log.properties''' (название файла может быть любым).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 log4j.logger.simple=DEBUG, nameLogAppender&lt;br /&gt;
 log4j.appender.nameLogAppender=org.apache.log4j.FileAppender&lt;br /&gt;
 log4j.appender.nameLogAppender.File=nameLogFile.log&lt;br /&gt;
 log4j.appender.nameLogAppender.layout=org.apache.log4j.SimpleLayout&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Первая строка указывает используемый уровень logger (DEBUG) и appender (nameLogAppender). Далее идут настройки appender: указание типа — FileAppender. В третьей строке указываем путь до файла журнала, а в последней — формат записи. Использовать экземпляр класса Logger можно примерно так (пример протоколирования приведен на диске в каталоге '''examples 3'''):&lt;br /&gt;
&amp;lt;source lang = &amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
File propertiesFile = new File(&amp;quot;log.properties&amp;quot;);&lt;br /&gt;
PropertyConfigurator.configure(propertiesFile.toString());&lt;br /&gt;
Logger logger = Logger.getLogger(&amp;quot;simple&amp;quot;);&lt;br /&gt;
logger.info(&amp;quot;the program has started&amp;quot;);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Документы XML ===&lt;br /&gt;
&lt;br /&gt;
=== Создание XML-документа ===&lt;br /&gt;
&lt;br /&gt;
=== Сохранение XML-документа ===&lt;br /&gt;
&lt;br /&gt;
=== Загрузка XML-документа ===&lt;br /&gt;
&lt;br /&gt;
=== Извлечение данных из XML-документа ===&lt;/div&gt;</summary>
		<author><name>Skryabin yuri</name></author>	</entry>

	<entry>
		<id>http://wiki.linuxformat.ru/wiki/LXF86:Java</id>
		<title>LXF86:Java</title>
		<link rel="alternate" type="text/html" href="http://wiki.linuxformat.ru/wiki/LXF86:Java"/>
				<updated>2008-03-13T10:00:25Z</updated>
		
		<summary type="html">&lt;p&gt;Skryabin yuri: /* Свободный доступ */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=== Хранение данных ===&lt;br /&gt;
''ЧАСТЬ 3: Даже самой замечательной программе надо откуда-то черпать данные для своей работы. Данные, как известно, хранятся в файлах. Тему продолжает '''Антон Черноусов'''.''&lt;br /&gt;
&lt;br /&gt;
В предыдущей статье из цикла, посвященного программированию на Java, были рассмотрены вопросы организации простых вычислений, ветвлений, циклов, а также генерации и обработки исключений.&lt;br /&gt;
&lt;br /&gt;
В течение третьего урока мы поговорим о работе с файлами, о протоколировании работы программы и коснемся методов работы с&lt;br /&gt;
XML-данными.&lt;br /&gt;
&lt;br /&gt;
=== Файлы — потоки ===&lt;br /&gt;
Сказочное королевство под руководством царевны Несмеяны (так как cупруг практически всегда отсутствовал), благодаря талантам и приобретенным навыкам, стало разрастаться, и результаты полюдья просто-напросто перестали помещаться в семейный чулан. Чтобы накапливать и хранить богатства, потребовались дополнительные помещения, роль которых для нас привычно играют файлы.&lt;br /&gt;
&lt;br /&gt;
Отношение к файлам в Java достаточно непростое: если рассматривать файл как устройство для ввода/вывода информации — с этой точ&lt;br /&gt;
ки зрения он подобен блоку памяти или экрану, интерфейс доступа к которому унифицирован: это поток. Но несмотря на унифицированный интерфейс, существует большое количество классов сходной функциональности, в которых легко запутаться.&lt;br /&gt;
&lt;br /&gt;
Поток можно представить в виде ленточного конвейера с последовательным размещением или извлечением данных, при использовании&lt;br /&gt;
которого задача программиста сводиться к осуществлению операций «поместить/читать» данные, а остальные детали реализации скрыты&lt;br /&gt;
от него.&lt;br /&gt;
&lt;br /&gt;
=== Чтение данных ===&lt;br /&gt;
Разнообразие классов для работы с файлами позволяет выбрать для себя ту связку, которая больше нравится. Лично я для чтения данных использую BufferedReader, InputStreamReader и FileInputStream. Собственно взаимодействие этих классов для программиста заканчивается в момент создания экземпляра BufferedReader, что делается следующим образом:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang = &amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
BufferedReader br = null;&lt;br /&gt;
br = new BufferedReader(new InputStreamReader(new FileInputStream(pathToFile), encoding));&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
В процессе создания участвуют строковые переменные, содержащие путь к файлу и кодировку, в которой производится считывание&lt;br /&gt;
данных: pathToFile и encoding. В классах, работающих с файлами, считается обязательным создавать переменную для кодировки по умолчанию:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang = &amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
protected static String DEFAULT_ENCODING = &amp;quot;UTF-8&amp;quot;;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Любой текстовый файл можно представить себе в виде набора строк, поэтому давайте реализуем метод для считывания содержимого&lt;br /&gt;
файла в массив String[]. Далее представлен метод rippedCurrentFile(path ToFile, encoding) класса FileRipper, который извлекает данные из файла с помощью метода readLine() экземпляра класса BufferedReader:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang = &amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
protected boolean rippedCurrentFile(String pathToFile, String encoding) {&lt;br /&gt;
  // connecting to file&lt;br /&gt;
  BufferedReader br = null;&lt;br /&gt;
  try {&lt;br /&gt;
    br = new BufferedReader(new InputStreamReader(new FileInputStream(pathToFile),encoding));&lt;br /&gt;
  } &lt;br /&gt;
  catch (UnsupportedEncodingException e) {&lt;br /&gt;
    this.error = FILE_ERROR_UNSUPPORTED_ENCODING; return false;&lt;br /&gt;
  } &lt;br /&gt;
  catch (FileNotFoundException e) {&lt;br /&gt;
    this.error = FILE_ERROR_NO_FILE; return false;&lt;br /&gt;
  }&lt;br /&gt;
  // ripping the file&lt;br /&gt;
  String str = null;&lt;br /&gt;
  ArrayList allStrings = new ArrayList();&lt;br /&gt;
  try {&lt;br /&gt;
    while (!(str = br.readLine()).equals(null)) { allStrings.add(str); }&lt;br /&gt;
  } &lt;br /&gt;
  catch (IOException e) {&lt;br /&gt;
    this.error = FILE_ERROR_IO_READ; return false;&lt;br /&gt;
  } &lt;br /&gt;
  catch (NullPointerException e) {&lt;br /&gt;
    this.error = FILE_ERROR_END_OF_FILE;&lt;br /&gt;
  }&lt;br /&gt;
  // free the resources&lt;br /&gt;
  try {&lt;br /&gt;
    br.close();&lt;br /&gt;
  } &lt;br /&gt;
  catch (IOException e) {&lt;br /&gt;
    this.error = FILE_ERROR_IO_CLOSE; return false;&lt;br /&gt;
  }&lt;br /&gt;
  this.allStrings = (String[]) allStrings.toArray(new String[0]); &lt;br /&gt;
  return true;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Полный код примера, в том числе код класса ConsoleToFileRipper, применяющий экземпляр класса FileRipper для извлечения данных из файла, можно найти на диске в каталоге '''examples 1'''.&lt;br /&gt;
&lt;br /&gt;
=== Запись данных ===&lt;br /&gt;
Процесс записи данных в файл хоть и отличается от чтения, но тоже достаточно похож на организацию конвейера. Для записи&lt;br /&gt;
я обычно использую связку BufferedWriter, OutputStreamWriter, FileOutputStream.&lt;br /&gt;
&amp;lt;source lang = &amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
BufferedWriter out;&lt;br /&gt;
out = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(pathToFile), encoding));&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Для освобождения ресурсов, которые используют экземпляры классов BufferedReader и BufferedWriter, необходимо вызвать метод&lt;br /&gt;
close().&lt;br /&gt;
&lt;br /&gt;
Далее приведу простой пример метода, который записывает строковый массив в файл (полный код метода расположен на диске в&lt;br /&gt;
директории '''examples 2'''):&lt;br /&gt;
&amp;lt;source lang = &amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
public boolean createCurrentFile(String pathToFile, String[] allStrings, String encoding){&lt;br /&gt;
  try {&lt;br /&gt;
    BufferedWriter out;&lt;br /&gt;
    out = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(pathToFile), encoding));&lt;br /&gt;
    for (int i = 0; i &amp;lt; allStrings.length; i++) {&lt;br /&gt;
      out.write(allStrings[i]); out.write(‘\n’);&lt;br /&gt;
    }&lt;br /&gt;
    out.close();&lt;br /&gt;
  } &lt;br /&gt;
  catch (IOException e) {&lt;br /&gt;
    e.printStackTrace(); &lt;br /&gt;
    return false;&lt;br /&gt;
  }&lt;br /&gt;
  return true;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Свободный доступ ===&lt;br /&gt;
В представленных ранее примерах доступ к данным осуществляется последовательно, что не всегда удобно (хотя в большинстве случаев именно такой доступ и используется). Для осуществления чтения и записи данных из файла в произвольном порядке существует специальный класс RandomAccessFile, экземпляр которого создается следующим образом:&lt;br /&gt;
&amp;lt;source lang = &amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
RandomAccessFile raf = new RandomAccessFile(pathToFile, mode);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
При этом pathToFile — путь до файла, а mode — режим работы. mode может принимать значения: r (только чтение), rw (чтение-запись), rws (чтение-запись с синхронным сохранением содержимого и метаданных), rwd (чтение-запись с синхронным сохранением содержимого файла). К сожалению, кодировку указать нельзя. Огромным преимуществом подхода является то, что с помощью метода getFilePointer() можно узнать текущее месторасположение указателя, а с помощью метода seek() можно передвинуть указатель в необходимое место в файле. Я предпочитаю не использовать данный класс — считайте это личным предубеждением.&lt;br /&gt;
&lt;br /&gt;
=== Протоколирование работы программы ===&lt;br /&gt;
&lt;br /&gt;
=== Документы XML ===&lt;br /&gt;
&lt;br /&gt;
=== Создание XML-документа ===&lt;br /&gt;
&lt;br /&gt;
=== Сохранение XML-документа ===&lt;br /&gt;
&lt;br /&gt;
=== Загрузка XML-документа ===&lt;br /&gt;
&lt;br /&gt;
=== Извлечение данных из XML-документа ===&lt;/div&gt;</summary>
		<author><name>Skryabin yuri</name></author>	</entry>

	<entry>
		<id>http://wiki.linuxformat.ru/wiki/LXF86:Java</id>
		<title>LXF86:Java</title>
		<link rel="alternate" type="text/html" href="http://wiki.linuxformat.ru/wiki/LXF86:Java"/>
				<updated>2008-03-13T09:57:15Z</updated>
		
		<summary type="html">&lt;p&gt;Skryabin yuri: /* Запись данных */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=== Хранение данных ===&lt;br /&gt;
''ЧАСТЬ 3: Даже самой замечательной программе надо откуда-то черпать данные для своей работы. Данные, как известно, хранятся в файлах. Тему продолжает '''Антон Черноусов'''.''&lt;br /&gt;
&lt;br /&gt;
В предыдущей статье из цикла, посвященного программированию на Java, были рассмотрены вопросы организации простых вычислений, ветвлений, циклов, а также генерации и обработки исключений.&lt;br /&gt;
&lt;br /&gt;
В течение третьего урока мы поговорим о работе с файлами, о протоколировании работы программы и коснемся методов работы с&lt;br /&gt;
XML-данными.&lt;br /&gt;
&lt;br /&gt;
=== Файлы — потоки ===&lt;br /&gt;
Сказочное королевство под руководством царевны Несмеяны (так как cупруг практически всегда отсутствовал), благодаря талантам и приобретенным навыкам, стало разрастаться, и результаты полюдья просто-напросто перестали помещаться в семейный чулан. Чтобы накапливать и хранить богатства, потребовались дополнительные помещения, роль которых для нас привычно играют файлы.&lt;br /&gt;
&lt;br /&gt;
Отношение к файлам в Java достаточно непростое: если рассматривать файл как устройство для ввода/вывода информации — с этой точ&lt;br /&gt;
ки зрения он подобен блоку памяти или экрану, интерфейс доступа к которому унифицирован: это поток. Но несмотря на унифицированный интерфейс, существует большое количество классов сходной функциональности, в которых легко запутаться.&lt;br /&gt;
&lt;br /&gt;
Поток можно представить в виде ленточного конвейера с последовательным размещением или извлечением данных, при использовании&lt;br /&gt;
которого задача программиста сводиться к осуществлению операций «поместить/читать» данные, а остальные детали реализации скрыты&lt;br /&gt;
от него.&lt;br /&gt;
&lt;br /&gt;
=== Чтение данных ===&lt;br /&gt;
Разнообразие классов для работы с файлами позволяет выбрать для себя ту связку, которая больше нравится. Лично я для чтения данных использую BufferedReader, InputStreamReader и FileInputStream. Собственно взаимодействие этих классов для программиста заканчивается в момент создания экземпляра BufferedReader, что делается следующим образом:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang = &amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
BufferedReader br = null;&lt;br /&gt;
br = new BufferedReader(new InputStreamReader(new FileInputStream(pathToFile), encoding));&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
В процессе создания участвуют строковые переменные, содержащие путь к файлу и кодировку, в которой производится считывание&lt;br /&gt;
данных: pathToFile и encoding. В классах, работающих с файлами, считается обязательным создавать переменную для кодировки по умолчанию:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang = &amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
protected static String DEFAULT_ENCODING = &amp;quot;UTF-8&amp;quot;;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Любой текстовый файл можно представить себе в виде набора строк, поэтому давайте реализуем метод для считывания содержимого&lt;br /&gt;
файла в массив String[]. Далее представлен метод rippedCurrentFile(path ToFile, encoding) класса FileRipper, который извлекает данные из файла с помощью метода readLine() экземпляра класса BufferedReader:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang = &amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
protected boolean rippedCurrentFile(String pathToFile, String encoding) {&lt;br /&gt;
  // connecting to file&lt;br /&gt;
  BufferedReader br = null;&lt;br /&gt;
  try {&lt;br /&gt;
    br = new BufferedReader(new InputStreamReader(new FileInputStream(pathToFile),encoding));&lt;br /&gt;
  } &lt;br /&gt;
  catch (UnsupportedEncodingException e) {&lt;br /&gt;
    this.error = FILE_ERROR_UNSUPPORTED_ENCODING; return false;&lt;br /&gt;
  } &lt;br /&gt;
  catch (FileNotFoundException e) {&lt;br /&gt;
    this.error = FILE_ERROR_NO_FILE; return false;&lt;br /&gt;
  }&lt;br /&gt;
  // ripping the file&lt;br /&gt;
  String str = null;&lt;br /&gt;
  ArrayList allStrings = new ArrayList();&lt;br /&gt;
  try {&lt;br /&gt;
    while (!(str = br.readLine()).equals(null)) { allStrings.add(str); }&lt;br /&gt;
  } &lt;br /&gt;
  catch (IOException e) {&lt;br /&gt;
    this.error = FILE_ERROR_IO_READ; return false;&lt;br /&gt;
  } &lt;br /&gt;
  catch (NullPointerException e) {&lt;br /&gt;
    this.error = FILE_ERROR_END_OF_FILE;&lt;br /&gt;
  }&lt;br /&gt;
  // free the resources&lt;br /&gt;
  try {&lt;br /&gt;
    br.close();&lt;br /&gt;
  } &lt;br /&gt;
  catch (IOException e) {&lt;br /&gt;
    this.error = FILE_ERROR_IO_CLOSE; return false;&lt;br /&gt;
  }&lt;br /&gt;
  this.allStrings = (String[]) allStrings.toArray(new String[0]); &lt;br /&gt;
  return true;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Полный код примера, в том числе код класса ConsoleToFileRipper, применяющий экземпляр класса FileRipper для извлечения данных из файла, можно найти на диске в каталоге '''examples 1'''.&lt;br /&gt;
&lt;br /&gt;
=== Запись данных ===&lt;br /&gt;
Процесс записи данных в файл хоть и отличается от чтения, но тоже достаточно похож на организацию конвейера. Для записи&lt;br /&gt;
я обычно использую связку BufferedWriter, OutputStreamWriter, FileOutputStream.&lt;br /&gt;
&amp;lt;source lang = &amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
BufferedWriter out;&lt;br /&gt;
out = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(pathToFile), encoding));&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Для освобождения ресурсов, которые используют экземпляры классов BufferedReader и BufferedWriter, необходимо вызвать метод&lt;br /&gt;
close().&lt;br /&gt;
&lt;br /&gt;
Далее приведу простой пример метода, который записывает строковый массив в файл (полный код метода расположен на диске в&lt;br /&gt;
директории '''examples 2'''):&lt;br /&gt;
&amp;lt;source lang = &amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
public boolean createCurrentFile(String pathToFile, String[] allStrings, String encoding){&lt;br /&gt;
  try {&lt;br /&gt;
    BufferedWriter out;&lt;br /&gt;
    out = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(pathToFile), encoding));&lt;br /&gt;
    for (int i = 0; i &amp;lt; allStrings.length; i++) {&lt;br /&gt;
      out.write(allStrings[i]); out.write(‘\n’);&lt;br /&gt;
    }&lt;br /&gt;
    out.close();&lt;br /&gt;
  } &lt;br /&gt;
  catch (IOException e) {&lt;br /&gt;
    e.printStackTrace(); &lt;br /&gt;
    return false;&lt;br /&gt;
  }&lt;br /&gt;
  return true;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Свободный доступ ===&lt;br /&gt;
&lt;br /&gt;
=== Протоколирование работы программы ===&lt;br /&gt;
&lt;br /&gt;
=== Документы XML ===&lt;br /&gt;
&lt;br /&gt;
=== Создание XML-документа ===&lt;br /&gt;
&lt;br /&gt;
=== Сохранение XML-документа ===&lt;br /&gt;
&lt;br /&gt;
=== Загрузка XML-документа ===&lt;br /&gt;
&lt;br /&gt;
=== Извлечение данных из XML-документа ===&lt;/div&gt;</summary>
		<author><name>Skryabin yuri</name></author>	</entry>

	<entry>
		<id>http://wiki.linuxformat.ru/wiki/LXF86:Java</id>
		<title>LXF86:Java</title>
		<link rel="alternate" type="text/html" href="http://wiki.linuxformat.ru/wiki/LXF86:Java"/>
				<updated>2008-03-13T09:53:14Z</updated>
		
		<summary type="html">&lt;p&gt;Skryabin yuri: /* Чтение данных */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=== Хранение данных ===&lt;br /&gt;
''ЧАСТЬ 3: Даже самой замечательной программе надо откуда-то черпать данные для своей работы. Данные, как известно, хранятся в файлах. Тему продолжает '''Антон Черноусов'''.''&lt;br /&gt;
&lt;br /&gt;
В предыдущей статье из цикла, посвященного программированию на Java, были рассмотрены вопросы организации простых вычислений, ветвлений, циклов, а также генерации и обработки исключений.&lt;br /&gt;
&lt;br /&gt;
В течение третьего урока мы поговорим о работе с файлами, о протоколировании работы программы и коснемся методов работы с&lt;br /&gt;
XML-данными.&lt;br /&gt;
&lt;br /&gt;
=== Файлы — потоки ===&lt;br /&gt;
Сказочное королевство под руководством царевны Несмеяны (так как cупруг практически всегда отсутствовал), благодаря талантам и приобретенным навыкам, стало разрастаться, и результаты полюдья просто-напросто перестали помещаться в семейный чулан. Чтобы накапливать и хранить богатства, потребовались дополнительные помещения, роль которых для нас привычно играют файлы.&lt;br /&gt;
&lt;br /&gt;
Отношение к файлам в Java достаточно непростое: если рассматривать файл как устройство для ввода/вывода информации — с этой точ&lt;br /&gt;
ки зрения он подобен блоку памяти или экрану, интерфейс доступа к которому унифицирован: это поток. Но несмотря на унифицированный интерфейс, существует большое количество классов сходной функциональности, в которых легко запутаться.&lt;br /&gt;
&lt;br /&gt;
Поток можно представить в виде ленточного конвейера с последовательным размещением или извлечением данных, при использовании&lt;br /&gt;
которого задача программиста сводиться к осуществлению операций «поместить/читать» данные, а остальные детали реализации скрыты&lt;br /&gt;
от него.&lt;br /&gt;
&lt;br /&gt;
=== Чтение данных ===&lt;br /&gt;
Разнообразие классов для работы с файлами позволяет выбрать для себя ту связку, которая больше нравится. Лично я для чтения данных использую BufferedReader, InputStreamReader и FileInputStream. Собственно взаимодействие этих классов для программиста заканчивается в момент создания экземпляра BufferedReader, что делается следующим образом:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang = &amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
BufferedReader br = null;&lt;br /&gt;
br = new BufferedReader(new InputStreamReader(new FileInputStream(pathToFile), encoding));&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
В процессе создания участвуют строковые переменные, содержащие путь к файлу и кодировку, в которой производится считывание&lt;br /&gt;
данных: pathToFile и encoding. В классах, работающих с файлами, считается обязательным создавать переменную для кодировки по умолчанию:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang = &amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
protected static String DEFAULT_ENCODING = &amp;quot;UTF-8&amp;quot;;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Любой текстовый файл можно представить себе в виде набора строк, поэтому давайте реализуем метод для считывания содержимого&lt;br /&gt;
файла в массив String[]. Далее представлен метод rippedCurrentFile(path ToFile, encoding) класса FileRipper, который извлекает данные из файла с помощью метода readLine() экземпляра класса BufferedReader:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang = &amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
protected boolean rippedCurrentFile(String pathToFile, String encoding) {&lt;br /&gt;
  // connecting to file&lt;br /&gt;
  BufferedReader br = null;&lt;br /&gt;
  try {&lt;br /&gt;
    br = new BufferedReader(new InputStreamReader(new FileInputStream(pathToFile),encoding));&lt;br /&gt;
  } &lt;br /&gt;
  catch (UnsupportedEncodingException e) {&lt;br /&gt;
    this.error = FILE_ERROR_UNSUPPORTED_ENCODING; return false;&lt;br /&gt;
  } &lt;br /&gt;
  catch (FileNotFoundException e) {&lt;br /&gt;
    this.error = FILE_ERROR_NO_FILE; return false;&lt;br /&gt;
  }&lt;br /&gt;
  // ripping the file&lt;br /&gt;
  String str = null;&lt;br /&gt;
  ArrayList allStrings = new ArrayList();&lt;br /&gt;
  try {&lt;br /&gt;
    while (!(str = br.readLine()).equals(null)) { allStrings.add(str); }&lt;br /&gt;
  } &lt;br /&gt;
  catch (IOException e) {&lt;br /&gt;
    this.error = FILE_ERROR_IO_READ; return false;&lt;br /&gt;
  } &lt;br /&gt;
  catch (NullPointerException e) {&lt;br /&gt;
    this.error = FILE_ERROR_END_OF_FILE;&lt;br /&gt;
  }&lt;br /&gt;
  // free the resources&lt;br /&gt;
  try {&lt;br /&gt;
    br.close();&lt;br /&gt;
  } &lt;br /&gt;
  catch (IOException e) {&lt;br /&gt;
    this.error = FILE_ERROR_IO_CLOSE; return false;&lt;br /&gt;
  }&lt;br /&gt;
  this.allStrings = (String[]) allStrings.toArray(new String[0]); &lt;br /&gt;
  return true;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Полный код примера, в том числе код класса ConsoleToFileRipper, применяющий экземпляр класса FileRipper для извлечения данных из файла, можно найти на диске в каталоге '''examples 1'''.&lt;br /&gt;
&lt;br /&gt;
=== Запись данных ===&lt;br /&gt;
&lt;br /&gt;
=== Свободный доступ ===&lt;br /&gt;
&lt;br /&gt;
=== Протоколирование работы программы ===&lt;br /&gt;
&lt;br /&gt;
=== Документы XML ===&lt;br /&gt;
&lt;br /&gt;
=== Создание XML-документа ===&lt;br /&gt;
&lt;br /&gt;
=== Сохранение XML-документа ===&lt;br /&gt;
&lt;br /&gt;
=== Загрузка XML-документа ===&lt;br /&gt;
&lt;br /&gt;
=== Извлечение данных из XML-документа ===&lt;/div&gt;</summary>
		<author><name>Skryabin yuri</name></author>	</entry>

	<entry>
		<id>http://wiki.linuxformat.ru/wiki/LXF86:Java</id>
		<title>LXF86:Java</title>
		<link rel="alternate" type="text/html" href="http://wiki.linuxformat.ru/wiki/LXF86:Java"/>
				<updated>2008-03-13T09:52:19Z</updated>
		
		<summary type="html">&lt;p&gt;Skryabin yuri: /* Чтение данных */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=== Хранение данных ===&lt;br /&gt;
''ЧАСТЬ 3: Даже самой замечательной программе надо откуда-то черпать данные для своей работы. Данные, как известно, хранятся в файлах. Тему продолжает '''Антон Черноусов'''.''&lt;br /&gt;
&lt;br /&gt;
В предыдущей статье из цикла, посвященного программированию на Java, были рассмотрены вопросы организации простых вычислений, ветвлений, циклов, а также генерации и обработки исключений.&lt;br /&gt;
&lt;br /&gt;
В течение третьего урока мы поговорим о работе с файлами, о протоколировании работы программы и коснемся методов работы с&lt;br /&gt;
XML-данными.&lt;br /&gt;
&lt;br /&gt;
=== Файлы — потоки ===&lt;br /&gt;
Сказочное королевство под руководством царевны Несмеяны (так как cупруг практически всегда отсутствовал), благодаря талантам и приобретенным навыкам, стало разрастаться, и результаты полюдья просто-напросто перестали помещаться в семейный чулан. Чтобы накапливать и хранить богатства, потребовались дополнительные помещения, роль которых для нас привычно играют файлы.&lt;br /&gt;
&lt;br /&gt;
Отношение к файлам в Java достаточно непростое: если рассматривать файл как устройство для ввода/вывода информации — с этой точ&lt;br /&gt;
ки зрения он подобен блоку памяти или экрану, интерфейс доступа к которому унифицирован: это поток. Но несмотря на унифицированный интерфейс, существует большое количество классов сходной функциональности, в которых легко запутаться.&lt;br /&gt;
&lt;br /&gt;
Поток можно представить в виде ленточного конвейера с последовательным размещением или извлечением данных, при использовании&lt;br /&gt;
которого задача программиста сводиться к осуществлению операций «поместить/читать» данные, а остальные детали реализации скрыты&lt;br /&gt;
от него.&lt;br /&gt;
&lt;br /&gt;
=== Чтение данных ===&lt;br /&gt;
Разнообразие классов для работы с файлами позволяет выбрать для себя ту связку, которая больше нравится. Лично я для чтения данных использую BufferedReader, InputStreamReader и FileInputStream. Собственно взаимодействие этих классов для программиста заканчивается в момент создания экземпляра BufferedReader, что делается следующим образом:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang = &amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
BufferedReader br = null;&lt;br /&gt;
br = new BufferedReader(new InputStreamReader(new FileInputStream(pathToFile), encoding));&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
В процессе создания участвуют строковые переменные, содержащие путь к файлу и кодировку, в которой производится считывание&lt;br /&gt;
данных: pathToFile и encoding. В классах, работающих с файлами, считается обязательным создавать переменную для кодировки по умолчанию:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang = &amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
protected static String DEFAULT_ENCODING = “UTF-8”;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Любой текстовый файл можно представить себе в виде набора строк, поэтому давайте реализуем метод для считывания содержимого&lt;br /&gt;
файла в массив String[]. Далее представлен метод rippedCurrentFile(path ToFile, encoding) класса FileRipper, который извлекает данные из файла с помощью метода readLine() экземпляра класса BufferedReader:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang = &amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
protected boolean rippedCurrentFile(String pathToFile, String encoding) {&lt;br /&gt;
  // connecting to file&lt;br /&gt;
  BufferedReader br = null;&lt;br /&gt;
  try {&lt;br /&gt;
    br = new BufferedReader(new InputStreamReader(new FileInputStream(pathToFile),encoding));&lt;br /&gt;
  } &lt;br /&gt;
  catch (UnsupportedEncodingException e) {&lt;br /&gt;
    this.error = FILE_ERROR_UNSUPPORTED_ENCODING; return false;&lt;br /&gt;
  } &lt;br /&gt;
  catch (FileNotFoundException e) {&lt;br /&gt;
    this.error = FILE_ERROR_NO_FILE; return false;&lt;br /&gt;
  }&lt;br /&gt;
  // ripping the file&lt;br /&gt;
  String str = null;&lt;br /&gt;
  ArrayList allStrings = new ArrayList();&lt;br /&gt;
  try {&lt;br /&gt;
    while (!(str = br.readLine()).equals(null)) { allStrings.add(str); }&lt;br /&gt;
  } &lt;br /&gt;
  catch (IOException e) {&lt;br /&gt;
    this.error = FILE_ERROR_IO_READ; return false;&lt;br /&gt;
  } &lt;br /&gt;
  catch (NullPointerException e) {&lt;br /&gt;
    this.error = FILE_ERROR_END_OF_FILE;&lt;br /&gt;
  }&lt;br /&gt;
  // free the resources&lt;br /&gt;
  try {&lt;br /&gt;
    br.close();&lt;br /&gt;
  } &lt;br /&gt;
  catch (IOException e) {&lt;br /&gt;
    this.error = FILE_ERROR_IO_CLOSE; return false;&lt;br /&gt;
  }&lt;br /&gt;
  this.allStrings = (String[]) allStrings.toArray(new String[0]); &lt;br /&gt;
  return true;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Полный код примера, в том числе код класса ConsoleToFileRipper, применяющий экземпляр класса FileRipper для извлечения данных из файла, можно найти на диске в каталоге '''examples 1'''.&lt;br /&gt;
&lt;br /&gt;
=== Запись данных ===&lt;br /&gt;
&lt;br /&gt;
=== Свободный доступ ===&lt;br /&gt;
&lt;br /&gt;
=== Протоколирование работы программы ===&lt;br /&gt;
&lt;br /&gt;
=== Документы XML ===&lt;br /&gt;
&lt;br /&gt;
=== Создание XML-документа ===&lt;br /&gt;
&lt;br /&gt;
=== Сохранение XML-документа ===&lt;br /&gt;
&lt;br /&gt;
=== Загрузка XML-документа ===&lt;br /&gt;
&lt;br /&gt;
=== Извлечение данных из XML-документа ===&lt;/div&gt;</summary>
		<author><name>Skryabin yuri</name></author>	</entry>

	<entry>
		<id>http://wiki.linuxformat.ru/wiki/LXF86:Java</id>
		<title>LXF86:Java</title>
		<link rel="alternate" type="text/html" href="http://wiki.linuxformat.ru/wiki/LXF86:Java"/>
				<updated>2008-03-13T09:36:27Z</updated>
		
		<summary type="html">&lt;p&gt;Skryabin yuri: /* Файлы — потоки */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=== Хранение данных ===&lt;br /&gt;
''ЧАСТЬ 3: Даже самой замечательной программе надо откуда-то черпать данные для своей работы. Данные, как известно, хранятся в файлах. Тему продолжает '''Антон Черноусов'''.''&lt;br /&gt;
&lt;br /&gt;
В предыдущей статье из цикла, посвященного программированию на Java, были рассмотрены вопросы организации простых вычислений, ветвлений, циклов, а также генерации и обработки исключений.&lt;br /&gt;
&lt;br /&gt;
В течение третьего урока мы поговорим о работе с файлами, о протоколировании работы программы и коснемся методов работы с&lt;br /&gt;
XML-данными.&lt;br /&gt;
&lt;br /&gt;
=== Файлы — потоки ===&lt;br /&gt;
Сказочное королевство под руководством царевны Несмеяны (так как cупруг практически всегда отсутствовал), благодаря талантам и приобретенным навыкам, стало разрастаться, и результаты полюдья просто-напросто перестали помещаться в семейный чулан. Чтобы накапливать и хранить богатства, потребовались дополнительные помещения, роль которых для нас привычно играют файлы.&lt;br /&gt;
&lt;br /&gt;
Отношение к файлам в Java достаточно непростое: если рассматривать файл как устройство для ввода/вывода информации — с этой точ&lt;br /&gt;
ки зрения он подобен блоку памяти или экрану, интерфейс доступа к которому унифицирован: это поток. Но несмотря на унифицированный интерфейс, существует большое количество классов сходной функциональности, в которых легко запутаться.&lt;br /&gt;
&lt;br /&gt;
Поток можно представить в виде ленточного конвейера с последовательным размещением или извлечением данных, при использовании&lt;br /&gt;
которого задача программиста сводиться к осуществлению операций «поместить/читать» данные, а остальные детали реализации скрыты&lt;br /&gt;
от него.&lt;br /&gt;
&lt;br /&gt;
=== Чтение данных ===&lt;br /&gt;
&lt;br /&gt;
=== Запись данных ===&lt;br /&gt;
&lt;br /&gt;
=== Свободный доступ ===&lt;br /&gt;
&lt;br /&gt;
=== Протоколирование работы программы ===&lt;br /&gt;
&lt;br /&gt;
=== Документы XML ===&lt;br /&gt;
&lt;br /&gt;
=== Создание XML-документа ===&lt;br /&gt;
&lt;br /&gt;
=== Сохранение XML-документа ===&lt;br /&gt;
&lt;br /&gt;
=== Загрузка XML-документа ===&lt;br /&gt;
&lt;br /&gt;
=== Извлечение данных из XML-документа ===&lt;/div&gt;</summary>
		<author><name>Skryabin yuri</name></author>	</entry>

	<entry>
		<id>http://wiki.linuxformat.ru/wiki/LXF84:OSDL</id>
		<title>LXF84:OSDL</title>
		<link rel="alternate" type="text/html" href="http://wiki.linuxformat.ru/wiki/LXF84:OSDL"/>
				<updated>2008-03-13T09:30:12Z</updated>
		
		<summary type="html">&lt;p&gt;Skryabin yuri: Содержание&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=== Что сделала для нас OSDL? ===&lt;br /&gt;
''Кажется, что The Open Source Development Labs (Лаборатория Разработки Открытого Кода) сидит на нескольких стульях – но знает ли кто-нибудь, чем конкретно она занимается? Расследование ведет '''Грэм Моррисон'''.''&lt;br /&gt;
&lt;br /&gt;
Прочтя интервью со Стюартом Коэном [Stuart Cohen] пару номеров назад, вы, наверное, захотели узнать побольше о его нанимателе.&lt;br /&gt;
Коэн – исполнительный директор OSDL, организации, образованной в 2000 г. консорциумом больших компаний, в том числе, CA, Hitachi, HP, IBM, Intel и NEC. Эти фирмы предоставили финансирование и получили центр разработки Open Source, беспристрастный и некоммерческий, который посвящен продвижению Linux (на что многие из них делают ставку) в большой бизнес. Это мир подготовительных комитетов и спецификаций, рабочих групп и официальных документов: частично – мозговой центр, частично – глобальный консорциум, и частично – Международное Спасение.&lt;br /&gt;
&lt;br /&gt;
«OSDL» звучит несколько отчужденно, и тем не менее лаборатория сильно влияет на большое сообщество Linux – не только потому, что платит зарплату Линусу Торвальдсу, но и потому, что эта организация позиционировала себя как «центр тяжести» (термин, от которого она теперь дистанцируется) Linux, в который мы все вносим свою лепту. OSDL открыта для всех, а не только для многонациональных конгломератов. Отдельные личности могут свободно присоединиться и принять участие во всевозможных рабочих группах.&lt;br /&gt;
&lt;br /&gt;
За лабораторией стоят хорошо продуманные и хорошо финансируемые проекты. Например, она сформировала фонд юридической защиты для помощи в борьбе пользователей Linux против угроз возбуждения судебных дел, ее рабочие группы разрабатывают исключительно подробные спецификации; ею нанято по меньшей мере 10 разработчиков из тех, что напрямую влияют на функции Linux-систем, используемых нами ежедневно – половина годового бюджета лаборатории, а это $5 млн., тратится на развитие технологий.&lt;br /&gt;
&lt;br /&gt;
Но от большого бизнеса не уйдешь. Любое дело OSDL, будь то тестовая лаборатория или сервисы технической поддержки, движимо желанием вывести Linuх на уровень предприятий. Фирмы-учредители задались направлением на совершенствование преимуществ открытого кода. Это означает, что они могут управлять политикой разработки и предлагать области исследований – если в этом&lt;br /&gt;
заинтересован каждый член. OSDL не отстраняет от дела ни своих членов, ни другие открытые инициативы.&lt;br /&gt;
&lt;br /&gt;
Хотя OSDL и «открытая», но все же оставляет ощущение некоторой загадочности. Поэтому мы собираемся присмотреться к некоторым сотрудникам OSDL и крупнейшим ее проектам и решить, что же служит стимулом для этой организации. Для сначала сразу предупредим: поскольку это большой бизнес, то будет много акронимов. Мы пытаемся поменьше употреблять их, но все же их будет&lt;br /&gt;
много. С другой стороны, мы постарались свести к функциональному минимуму использование слова «рычаг», так что можете читать без опасения запутаться.&lt;br /&gt;
&lt;br /&gt;
[[Image:Img_84_39_1.jpg|right|thumb|Трудоустройство Линуса Торвальдса дало OSDL рекламную раскрутку.]]&lt;br /&gt;
[[Image:Img_84_39_2.jpg|right|thumb|Эндрю Мортон все время пребывания в OSDL занимался ядром.]]&lt;br /&gt;
[[Image:Img_84_39_3.jpg|right|thumb|Тридж ушел, как только закончил работу над Samba 4.]]&lt;br /&gt;
&lt;br /&gt;
=== Хакеры высокого полета ===&lt;br /&gt;
''Вот реальные причины важности OSDL.''&lt;br /&gt;
&lt;br /&gt;
Одной из причин известности OSDL является то, что в ней работают высококлассные хакеры ядра. Отчасти это потому, что она любит фанфары, а отчасти потому, что никто не сможет игнорировать организацию, трудоустроившую Торвальдса. Альтруистический аспект мотивации найма на работу Линуса Торвальдса, Эндрю Мортона и иже с ними в том, что OSDL хотела предоставить им условия разработки без конфликтов с другими обязанностями, чтобы эти два разработчика смогли целиком сосредоточиться на разработке ядра Linux. Но нельзя отрицать, что OSDL получает свою долю аплодисментов, когда люди видят ее логотип на их визитных карточках. &lt;br /&gt;
&lt;br /&gt;
Нет ни одного пресс-релиза от OSDL, который бы не включал следующую сноску: «OSDL – спонсор Линуса Торвальдса,&lt;br /&gt;
создателя ядра Linux – призвана ускорить рост и адаптацию операционных систем на основе Linux на предприятиях». Без сомнения, немалой частью оказываемого ей доверия OSDL обязана найму Линуса Торвальдса, человека, с которого все началось. До перехода в OSDL в июне 2003 г., Торвальдс был сотрудником корпорации Transmeta (члена OSDL), разрешавшей ему в рабочее время повозиться с ядром Linux, помимо разработки ее собственного ПО. Переход позволил Торвальдсу сосредоточиться исключительно на основных&lt;br /&gt;
компонентах ядра Linux. &lt;br /&gt;
&lt;br /&gt;
Итак, Линус впервые стал официально получать зарплату за сопровождение ядра Linux и координацию процесса разработки. Стюарт Коэн сказал тогда: «Принятие Линусом предложения присоединиться к нам подтверждает важность&lt;br /&gt;
нашей миссии. OSDL – единственная организация, в которой разработчики Linux, потребители и дистрибьюторы могут участвовать на равных. Дополнение лаборатории взглядами и руководством Линуса увеличивает нашу значимость для всех трех групп».&lt;br /&gt;
&lt;br /&gt;
Эндрю Мортон присоединился к Линусу в OSDL через месяц, в июле 2003 г. Мортон – «хранитель» ядра 2.6 (Торвальдс работает над текущей версией ядра), то есть лицо, ответственное за включение заплаток от третьих лиц в древо ядра текущей версии. Недавно, он, к недоумению многих, предложил посвятить следующий цикл разработки ядра исправлению ошибок, закравшихся в текущую версию.&lt;br /&gt;
Было очень ценно, что два основных разработчика Linux работают в одной компании, причем бок о бок. Но в августе Мортон ушел в Google. Это может нарушить нейтральность, которой разработчики наслаждались в OSDL, где отсутствовало прямое давление со стороны крупных фирм, являющихся частью OSDL.&lt;br /&gt;
&lt;br /&gt;
==== Теплица для ядра ====&lt;br /&gt;
&lt;br /&gt;
OSDL получила своего второго сотрудника в январе 2005 г., когда ее ряды пополнил Эндрю Триджелл, ведущий разработчик Samba – одного из самых важных существующих проектов с открытым кодом. Без Samba мы не могли бы совместно использовать любые файлы или принтеры с Windows-машинами в локальной сети, а это необходимое звено при развертывании Linux в любом офисе или на предприятии. OSDL позволила Триджеллу работать над ней полный рабочий день, но, завершив запланированные работы над четвертой версией комплекса приложений Samba, он ее покинул и вернулся на свою предыдущую должность в IBM, оставаясь лидером проекта Samba. Уходя, Триджелл выразил благодарность OSDL за ее участие в проекте: «Обладать временем, позволяющим сосредоточиться только на одном проекте, действительно здорово. Большое спасибо OSDL за участие и поддержку разработки Samba».&lt;br /&gt;
&lt;br /&gt;
=== Устанавливая стандарты ===&lt;br /&gt;
&lt;br /&gt;
''Если для внедрения Linux на предприятии требуется поработать с бумагами, то OSDL как раз и может здесь помочь.''&lt;br /&gt;
&lt;br /&gt;
Как и следовало ожидать, OSDL заинтересована в коммерческом успехе проектов, которые она финансирует и в которых участвует. В частности, за последние несколько лет созданы три рабочих группы, где представители фирм-членов OSDL встречаются для проработки спецификаций и применяют свои технические знания для решения наболевшего вопроса об ускорении внедрения Linux в трех областях.&lt;br /&gt;
&lt;br /&gt;
Наверху – рабочая группа Carrier Grade Linux (CGL), проталкивающая Linux в бурно разрастающийся телекоммуникационный бизнес. Посередине – группа Data Center Linux (DCL). Ее любимое слово – «рычаги», и она старается открыть для Linux рынок вычислительных центров крупных корпораций. И, наконец, группа Desktop Linux (DTL) сосредоточена на том, что понятно нам всем, а именно на продвижении Linux в настольные среды, типичные для офисов.&lt;br /&gt;
&lt;br /&gt;
==== Для телекоммуникаций ====&lt;br /&gt;
&lt;br /&gt;
Внедрение в области, традиционно использующие проприетарные решения – одна из главных задач OSDL, и есть одна область, в которой можно особенно поживиться. Это индустрия телекоммуникаций. Здесь традиционно вкладываются средства в проприетарные оборудование и программное обеспечение, и безопасная, стабильная и расширяемая Linux-альтернатива принесла бы немало выгоды. Решение от OSDL известно как Carrier Grade Linux (CGL – отказоустойчивый Linux): это спецификации системы, надежной более чем на 99.999% – всего пять минут на отказ в год. Но некоторые установки требуют даже большей надежности, около 99.9999%, то есть не более 30 секунд на отказ в год. Даже при знаменитой безопасности Linux необходимо многое изменить, чтобы гарантировать такое качество.&lt;br /&gt;
&lt;br /&gt;
В январе 2002 г. OSDL сформировала рабочую группу CGL (для коллекционеров акронимов – CGL-WG), чтобы создать для Linux комитет по телекоммуникациям. Основная задача группы – утверждение стандарта, который обеспечит доступную и высокоэффективную операционную систему Linux с прекрасной поддержкой, способную напрямую конкурировать с готовыми и заказными проприетарными решениями, получающими все большее распространение. Участие в ней приняли 24 организации – члены OSDL, а учредительские&lt;br /&gt;
обязанности легли на плечи IBM, MontaVista (известной благодаря своей real-time версии ядра Linux), Intel и NTT Network Service Systems Labs, возглавляющей подкомитет разработки. К настоящему моменту имеется пять версий спецификации. Версия 3.1 вышла в июне 2005. Заговорщики из OSDL работают над версией 3.2 и намерены выпустить ее в этом году.&lt;br /&gt;
&lt;br /&gt;
В спецификации CGL-WG девять основных положений, среди которых:&lt;br /&gt;
*Соответствие стандартам&lt;br /&gt;
&lt;br /&gt;
Это действительно залог нормальной работы CGL-WG с другими стандартами Linux и индустрии телекоммуникаций. Сюда включаются Linux Standard Base (LSB), POSIX, IPv6 и PCI Industrial Computer Manufacturer’s Group.&lt;br /&gt;
*Платформа&lt;br /&gt;
&lt;br /&gt;
Любая CGL-система накладывает специфические требования на оборудование. Сюда входит «горячая» замена, удаленная загрузка, бездисковое выполнение приложений через сеть и архитектура Advanced Telecom Computing Architecture [Продвинутая архитектура телекоммуникационных вычислений – серия спецификаций промышленных стандартов, разработанных для следующего поколения отказоустойчивого оборудования и ПО].&lt;br /&gt;
&lt;br /&gt;
*Работоспособность&lt;br /&gt;
&lt;br /&gt;
Поддержка системы в рабочем состоянии, чтобы все ее сервисы были всегда доступны, очень важна, и конкретным поставщикам приходится вносить множество изменений в ядро Linux. MontaVista – хороший пример дистрибьютора, самостоятельно переделавшего ядро Linux для удовлетворения повышенным требованиям.&lt;br /&gt;
&lt;br /&gt;
*Удобство обслуживания&lt;br /&gt;
&lt;br /&gt;
Машина, работающая постоянно, должна иметь возможность сервисного обслуживания, а значит, и поставлять в процессе работы материалы для диагностики, в форме дампов активного ядра или динамической отладочной информации.&lt;br /&gt;
&lt;br /&gt;
*Кластеризация&lt;br /&gt;
&lt;br /&gt;
Запуск приложений на кластерах часто является единственным способом получения высоких уровней доступности, требуемых CGL. Кластер обеспечивает повышенную производительность и резервирование использованием параллельных ресурсов. Кластеризация настолько важна, что породила свой собственный проект OSDL.&lt;br /&gt;
&lt;br /&gt;
Остальные четыре положения спецификации CGL касаются производительности, безопасности, расширяемости и создания инструментов поддержки приложений. HP сделала хороший шаг в начале этого года, зарегистрировав Debian Sarge под CGL версии 2.02, что привело к появлению внутри Debian подпроекта по созданию отказоустойчивого дистрибутива Linux, удовлетворяющего спецификации CGL.&lt;br /&gt;
&lt;br /&gt;
OSDL хочет выглядеть скорее сторонником Linux корпоративного уровня, уровня вычислительных центров, а не проталкивать открытый код на машины меньшего размера или даже на настольные компьютеры. Частично это связано с техническими аспектами CGL, а также с тем, что OSDL содержит и управляет рабочую группу DCL, цель которой – установка Linux в хранилищах данных с водяным и воздушным охлаждением некоторых крупных корпораций, многие из которых, так уж вышло, являются членами OSDL, но есть и фирмы вроде Siemens AG и Unisys.&lt;br /&gt;
&lt;br /&gt;
==== В базе данных – пингвины?! ====&lt;br /&gt;
&lt;br /&gt;
Поскольку CGL-спецификация очень тщательна, рабочая группа DCL может использовать ее в качестве стартовой точки для&lt;br /&gt;
высококлассного центра обработки данных. Вычислительные центры, объединяющие корпоративные сервера приложений,&lt;br /&gt;
базы данных и т.д., лежат в сфере ИТ с высокими стандартами. Цели группы DCL разбиты на три области деятельности,&lt;br /&gt;
обозначенные как Передний край (Edge), Приложения, База данных. Группа определяет «Край» как сервер, где наряду&lt;br /&gt;
с web-сервисами имеются edge-приложения – в основном ради улучшения производительности путем использования&lt;br /&gt;
промежуточного сервера для передачи запросов к сервисам, запущенным на других машинах. Приложения и База данных&lt;br /&gt;
в объяснениях не нуждаются.&lt;br /&gt;
&lt;br /&gt;
Плодом работы группы является версия 1.2 документа, озаглавленного «Цели и Возможности DCL» и впервые выпущенного еще в 2004. Это огромный документ с добавками от Sun, HP, IBM и Intel. Он похож скорее на техническую спецификацию, в нем приводится список более 300 возможностей, которые, как считает группа, важны для принятия Linux предприятиями. Например, приоритет номер один – возможность расширения до 16 CPU (пожалуй, уже маловато), асинхронный сетевой ввод/вывод и «горячая» замена процессоров,&lt;br /&gt;
памяти, а также устройств PCI/PCI-X.&lt;br /&gt;
&lt;br /&gt;
==== На рабочем столе ====&lt;br /&gt;
&lt;br /&gt;
Не удивительно, что самая молодая рабочая группа OSDL нацелена на настольный Linux. OSDL, видимо, понадеялась, что образование группы – в начале 2003 г. – будет ответом на критику заботы о внедрении Linux только на корпоративный рынок. И верно, образование рабочей группы DTL дало всему сообществу Linux возможность включиться в то, в чем оно имеет непосредственный опыт, и OSDL признает, что потенциальный размах этого проекта может затмить обе другие ее инициативы. Но группа отнюдь не чурается предприятий, и Desktop Linux включает области, которые вы не сразу отнесете к открытому рабочему столу – например, киоски и рабочие станции с фиксированным набором функций.&lt;br /&gt;
&lt;br /&gt;
Вы будете разочарованы, если ожидали больше действий и меньше создания спецификаций – количество бумажной работы остается обильным. DTL формулирует свою миссию как «работа с сообществом Open Source с целью выявления большого набора моделей настольного Linux, разработки спецификации и предоставлению рекомендаций.» Вы можете найти спецификацию версии 1.0 на web-сайте OSDL, и в отличие от спецификаций CGL и DCL, она удобочитаема!&lt;br /&gt;
&lt;br /&gt;
В настоящее время DTL работает при содействии представителей AMD, Novell, Intel и IBM. Одной из их наиболее интересных работ является не код, а результаты исследования, проведенного в октябре 2005 г., чтобы определить фокус действий рабочей группы.&lt;br /&gt;
ИТ-профессионалам, внедрившим или думающим о внедрении настольного Linux в своих учреждениях, были заданы вопросы об использовании Linux. Было опрошено 3300 респондентов, и результаты удивили многих. Самым неожиданным оказался ответ на вопрос о причине выбора Linux ИТ-профессионалами. Это не экономия денег и не повышенная безопасность, как предсказывали многие&lt;br /&gt;
эксперты, а чей-то совет. Люди использовали Linux и были им так довольны, что рекомендовали коллегам. Электронная&lt;br /&gt;
почта, офисные инструменты и web-браузеры были признаны критически важными приложениями, а дистрибутив Ubuntu оказался самым популярным. Естественно, что результаты опроса (см. [http://www.osdl.org/dtl/DTL_Survey_Report_Nov2005.pdf[www.osdl.org/dtl/DTL_Survey_Report_Nov2005.pdf]]) вызвали много разговоров в сообществе Linux.&lt;br /&gt;
&lt;br /&gt;
==== Молчаливый партнер ====&lt;br /&gt;
Критиковать OSDL за разработку одной спецификации за другой без написания хотя бы строки кода легко, но как раз это&lt;br /&gt;
и необходимо корпоративному рынку, на который OSDL пытается пробиться. Что нам нравится меньше, так это отсутствие&lt;br /&gt;
диалога с большим сообществом Linux – обычные пользователи Linux остаются за бортом любых разработок, выполняе-&lt;br /&gt;
мых для соответствия большому бизнесу. Хороший пример – написание данной статьи, потому как даже нам было трудно&lt;br /&gt;
получить комментарии или отзывы от людей из OSDL. А каковы шансы среднего раздраженного пользователя Linux? &lt;br /&gt;
&lt;br /&gt;
Если бы OSDL не твердила столь часто, что она является «центром тяжести» разработки Linux, мы были бы счастливы причислить OSDL к компаниям вроде CollabNet, продвигающей открытые стандарты и изменяющей способ ведения бизнеса крупными предприятиями. Но это не так. OSDL финансируется несколькими крупнейшими фирмами ИТ-бизнеса и наняла двух самых влиятельных из имеющихся разработчиков Linux. Если OSDL желает рассеять дымовую завесу, скрывающую ее действия и мотивы, то ей необходимо уделять&lt;br /&gt;
больше внимания взаимодействию с сообществом. Когда это случится, Linux действительно созреет для предприятий.&lt;br /&gt;
----&lt;br /&gt;
=== Проект Open Driver (врезка) ===&lt;br /&gt;
В поисках новых альтернатив, OSDL часто затевает и финансирует проекты. Наиболее масштабные ее кампании выросли из поддержки открытого форума San Francisco Linux World Expo в августе 2005. Форум был посвящен обсуждению препятствий разработке драйверов с открытым кодом, и на нем присутствовало много разработчиков драйверов ядра. Форум обозначил потребность в централизации разработки драйверов – явно в унисон с философией «центра притяжения» OSDL, и лаборатория взяла на себя создание web-сайта, способного играть роль центра разработки драйверов.&lt;br /&gt;
&lt;br /&gt;
В результате возник проект Open Driver, с домашней страницей [http://developer.osdl.org/dev/opendrivers[http://developer.osdl.org/dev/opendrivers]]. Сайт содержит новейшую информацию, необходимую для создания и установки ваших собственных драйверов. Число категорий драйверов стало заметно&lt;br /&gt;
больше изначальных пяти (носители, сеть, принтеры, видео и звук), охватив большинство других настольных устройств; среди них – сканеры, MP3-плейеры и цифровые камеры.&lt;br /&gt;
&lt;br /&gt;
Оригинального контента на сайте не слишком много. Вместо этого, каждая категория предоставляет список самых свежих сетевых ресурсов по вашему оборудованию. Цель сайта в том, чтобы разработчики драйверов, начинающие свой путь в Linux и Open Source, имели центральный репозиторий и понимание, с чего начать. Проект Open Driver содержит свои собственные wiki и списки рассылки, а также учебный семинар, в этом году совпавший с OSCon в Портленде, штат Орегон.&lt;br /&gt;
&lt;br /&gt;
=== Почему важны спецификации (врезка) ===&lt;br /&gt;
Для корпорации среднего размера любые инвестиции в новую технологию связаны с удовлетворением большому списку требований.&lt;br /&gt;
Необходимо проверить спецификации любого будущего оборудования, а каждый производитель устройств будет предоставлять свои &lt;br /&gt;
собственные спецификации. Вот тут и появляется OSDL. Она избавляет дистрибьюторов Linux от проблем создания своих собственных спецификаций, передавая все полученные из опыта знания в комитет, занятый формированием спецификаций. И все это делается открыто – любой может загрузить последнюю версию каждой спецификации, прочитать протоколы совещаний и списки рассылки рабочих групп, предоставляемые OSDL.&lt;br /&gt;
&lt;br /&gt;
=== Проекты, о которых стоит знать... (врезка) ===&lt;br /&gt;
OSDL наделала много шума из продвижения Linux на корпоративный рынок, но она не только готовит спецификации. Вот несколько более приземленных проектов:&lt;br /&gt;
*Создание Фонда Юридической защиты Linux&lt;br /&gt;
В начале 2004 г., когда была серьезная угроза судебных исков со стороны группы SCO ко всем использующим ОС Linux, OSDL создала Фонд Юридической Защиты Linux, выделив $10 млн. для помощи конечным пользователям, втянутым в битву с SCO.&lt;br /&gt;
*Сертификат разработчика о Происхождении (Developer’s Certificate of Origin)&lt;br /&gt;
Другим результатом тяжбы с SCO стало понимание необходимости отслеживания вклада отдельных программистов в разработку ядра. OSDL приняла меры (и не удивительно, коли в ней работают два основных разработчика ядра) и выступила с Сертификатом Разработчика о Происхождении. Он состоит из нескольких параграфов, снабженных цифровой подписью, чтобы корректно описать ваш&lt;br /&gt;
вклад в древо исходного кода ядра. &lt;br /&gt;
*Проект Patent Commons&lt;br /&gt;
Законодательство о патентах на ПО изменило лицо разработки приложений в США и вызвало резонанс в остальном мире. Это еще одна угроза будущему разработки приложений с открытым кодом. Проект был создан в августе 2005 г. после внезапного ливня патентов, пожертвованных сообществу Open Source крупными организациями вроде Sun Microsystems, IBM и Nokia. Проект, как и другие инициативы OSDL, разработан для того, чтобы играть роль центра и способствовать использованию открытых патентов на законных основаниях.&lt;/div&gt;</summary>
		<author><name>Skryabin yuri</name></author>	</entry>

	<entry>
		<id>http://wiki.linuxformat.ru/wiki/LXF85:Java</id>
		<title>LXF85:Java</title>
		<link rel="alternate" type="text/html" href="http://wiki.linuxformat.ru/wiki/LXF85:Java"/>
				<updated>2008-03-13T09:28:03Z</updated>
		
		<summary type="html">&lt;p&gt;Skryabin yuri: Содержание&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=== Считалочки ===&lt;br /&gt;
''ЧАСТЬ 2: Мало сыграть свадьбу – надо еще научиться вести семейный бюджет, выполнять одну и ту же работу каждый день и принимать судьбоносные решения. '''Антон Черноусов''' продолжает учить монархическую чету премудростям Java.''&lt;br /&gt;
&lt;br /&gt;
В предыдущей статье были рассмотрены основы объектно-ориентированного языка программирования Java: инкапсуляция,&lt;br /&gt;
наследование, полиморфизм. Мы создали простое приложение, в котором женили короля на царевне Несмеяне.&lt;br /&gt;
&lt;br /&gt;
Сегодня мы поговорим о простых типах (числах), о ветвлениях, циклах, а также об исключениях.&lt;br /&gt;
=== Простые числа и их братья ===&lt;br /&gt;
Итак, мы оставили нашу царевну Несмеяну в семейном гнезде, где она в скором времени добралась до казны государства. Ей пришлось&lt;br /&gt;
освоить нехитрую математику – отнимать и делить: ведь казна требует строго учета, и никакая программа не обходится без вычислений. Без них невозможно создать даже самую простую систему учета и контроля, а мадам необходимо наладить нетривиальный учет бюджетных средств.&lt;br /&gt;
&lt;br /&gt;
Для реализации арифметических операций в Java существует семь арифметических операторов, которые работают с любыми числовыми типами: сложение +, вычитание –, умножение *, деление /, остаток %, унарный минус -val и унарный плюс +val, а также шесть примитивных типов переменных для выполнения арифметических операций:&lt;br /&gt;
{| border = &amp;quot;1&amp;quot; cellpadding=&amp;quot;2&amp;quot;&lt;br /&gt;
 !Тип переменной&lt;br /&gt;
 !Разрядность&lt;br /&gt;
 !Описание&lt;br /&gt;
 |-&lt;br /&gt;
 |Byte||align=&amp;quot;center&amp;quot;|8||Целое со знаком&lt;br /&gt;
 |-&lt;br /&gt;
 |Short||align=&amp;quot;center&amp;quot;|16||Целое со знаком&lt;br /&gt;
 |-&lt;br /&gt;
 |Int||align=&amp;quot;center&amp;quot;|32||Целое со знаком&lt;br /&gt;
 |-&lt;br /&gt;
 |Long||align=&amp;quot;center&amp;quot;|64||Целое со знаком&lt;br /&gt;
 |-&lt;br /&gt;
 |Float||align=&amp;quot;center&amp;quot;|32||Число с плавающей точкой&lt;br /&gt;
 |-&lt;br /&gt;
 |Double||align=&amp;quot;center&amp;quot;|64||Число с плавающей точкой&lt;br /&gt;
 |}&lt;br /&gt;
&lt;br /&gt;
Значение типов byte и short при выполнении вычислений переопределяется int, поэтому использование этих типов целесообразно для&lt;br /&gt;
хранения небольших значений для уменьшения объема используемой оперативной памяти.&lt;br /&gt;
&amp;lt;source lang = &amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
int iA = 10;&lt;br /&gt;
byte bB = 12;&lt;br /&gt;
int iC = iA + bB;&lt;br /&gt;
System.out.println(&amp;quot;Сумма А и B = &amp;quot; + iC);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Выше приведен пример выполнения арифметической операции с использованием переменных различных типов. Результат – целое число типа int. Для преобразования типа переменной, например, в тип с более низкой разрядностью, необходимо воспользоваться специальными языковыми конструкциями:&lt;br /&gt;
&amp;lt;source lang = &amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
double dD = 10.2;&lt;br /&gt;
double dE = 12.23;&lt;br /&gt;
float fF = (float) (dD + dE);&lt;br /&gt;
System.out.println(fF);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Логика и выбор ===&lt;br /&gt;
Чтобы провести ревизию налоговой службы правильно, Несмеяне пришлось разобраться с налоговым кодексом, а там без поллитра и знаний логических операций не обойтись. &lt;br /&gt;
&lt;br /&gt;
Для представления логических значений в Java присутствует простой тип boolean, который принимает значения true или false. Для проведения различных логических операций можно использовать ниже перечисленные операторы:&lt;br /&gt;
&lt;br /&gt;
{| border = &amp;quot;1&amp;quot; cellpadding=&amp;quot;2&amp;quot;&lt;br /&gt;
 !Тип операторов&lt;br /&gt;
 !Операторы&lt;br /&gt;
 |-&lt;br /&gt;
 |операторы отношений&lt;br /&gt;
 |align = &amp;quot;center&amp;quot;| &amp;lt; &amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp; &amp;gt; &amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp; &amp;gt;= &amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp; &amp;lt;= &amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp; instanceof&lt;br /&gt;
 |-&lt;br /&gt;
 |операторы равенства||align = &amp;quot;center&amp;quot;|== &amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp; !=&lt;br /&gt;
 |-&lt;br /&gt;
 |поразрядное И||align = &amp;quot;center&amp;quot;|&amp;amp;&lt;br /&gt;
 |-&lt;br /&gt;
 |поразрядное исключающее ИЛИ||align = &amp;quot;center&amp;quot;|^&lt;br /&gt;
 |-&lt;br /&gt;
 |поразрядное включающее ИЛИ||align = &amp;quot;center&amp;quot;|&amp;amp;#448;&lt;br /&gt;
 |-&lt;br /&gt;
 |логическое И||align = &amp;quot;center&amp;quot;|&amp;amp;&amp;amp;&lt;br /&gt;
 |-&lt;br /&gt;
 |логическое ИЛИ||align = &amp;quot;center&amp;quot;|&amp;amp;#449;&lt;br /&gt;
 |}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Пока Несмеяна разбирается в дебрях налогового кодекса, мы для иллюстрации работы с логическими выражениями обратимся к методу&lt;br /&gt;
primeNumberCheckUp(int numberForCheck), который выясняет, является ли переданное ему число простым.&lt;br /&gt;
&amp;lt;source lang = &amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
private boolean primeNumberCheckUp(int numberForCheck) {&lt;br /&gt;
  boolean result = true;&lt;br /&gt;
  if (numberForCheck != 1 || numberForCheck != 2 || numberForCheck != 3) {&lt;br /&gt;
    for (int currentNumber = 2; currentNumber &amp;lt; numberForCheck; currentNumber++) {&lt;br /&gt;
      if (numberForCheck % currentNumber == 0) {&lt;br /&gt;
        result = false;&lt;br /&gt;
      }&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
  return result;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
В primeNumberCheckUp использованы две замечательные конструкции: оператор выбора по условию или условный оператор, и цикл.&lt;br /&gt;
Условный оператор if имеет следующий синтаксис:&lt;br /&gt;
&amp;lt;source lang = &amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
if (логическое выражение) {&lt;br /&gt;
           операторы группы 1;&lt;br /&gt;
}&lt;br /&gt;
else {&lt;br /&gt;
           операторы группы 2;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
В вышеописанном методе использована упрощенная конструкция (без else), а для вычисления логического выражения использованы&lt;br /&gt;
операторы: != (не равно) и || (логическое «или»). В полной конструкции в случае истинности логического выражения выполняются операторы группы 1, иначе – группы 2. &lt;br /&gt;
&lt;br /&gt;
Вместо if для управления выполнением кода может быть использована специальная конструкция switch. В рамках этой конструкции&lt;br /&gt;
вычисляется целочисленное выражение, и в соответствии с полученным результатом ведется поиск соответствующего значения блока&lt;br /&gt;
case.&lt;br /&gt;
&amp;lt;source lang = &amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
int flag = 6;&lt;br /&gt;
switch (flag) {&lt;br /&gt;
  case 1: {&lt;br /&gt;
    System.out.println(&amp;quot;Царевна в спальне №1&amp;quot;);&lt;br /&gt;
    break;&lt;br /&gt;
  }&lt;br /&gt;
  case 5: {&lt;br /&gt;
    System.out.println(&amp;quot;Царевна в спальне №5&amp;quot;);&lt;br /&gt;
    break;&lt;br /&gt;
  }&lt;br /&gt;
  default: {&lt;br /&gt;
    System.out.println(&amp;quot;Кто тут знает, где царевна?&amp;quot;);&lt;br /&gt;
    break;&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Обратите внимание на оператор break, который обеспечивает немедленный выход из любого блока, а в примере выше прекращает дальнейшую обработку операторов конструкции switch, а также на блок операторов default – этот блок необязательный, он выполняется в случае, если выражение, удовлетворяющие условию, не было найдено среди case.&lt;br /&gt;
&lt;br /&gt;
=== Циклы ===&lt;br /&gt;
Разобравшись, как все устроено в королевстве, Несмеяна поняла, что все подчиняется принципу «Украл, выпил, в тюрьму» – точнее, во Дворец до следующего месяца. По кругу.&lt;br /&gt;
&lt;br /&gt;
Для реализации «кругового» процесса в Java существует три вида циклов: for, while и do-while. С циклом for мы уже вы встречались в методе primeNumberCheckUp, продемонстрированном ранее, синтаксис этой конструкции следующий:&lt;br /&gt;
&amp;lt;source lang = &amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
for (инициализация; логическое выражение; приращение) {&lt;br /&gt;
           операторы;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
В рамках инициализации производится объявление и установка значений временных переменных. Цикл выполняется до тех пор, пока&lt;br /&gt;
логическое выражение истинно. На каждой итерации цикла производится приращение временных переменных.&lt;br /&gt;
&lt;br /&gt;
Две другие конструкции циклов можно назвать однояйцевыми близнецами, если бы не маленькое отличие в их использовании. При&lt;br /&gt;
использования цикла while проверка условия осуществляется до выполнения блока операторов, а в конструкции do-while – после него, то есть действия внутри цикла отрабатывают хотя бы раз. Например, процесс одиночной попойки короля от счастья, что он женат, на языке Java можно описать так:&lt;br /&gt;
&amp;lt;source lang = &amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
int i = 100;&lt;br /&gt;
while (i &amp;gt; 0) {&lt;br /&gt;
  System.out.println(i + &amp;quot; бутылок пива стояло на столе, одну уговорил&amp;quot;);&lt;br /&gt;
  i--;&lt;br /&gt;
}&lt;br /&gt;
System.out.println(&amp;quot;Все выпил, да!&amp;quot;);&lt;br /&gt;
int tankard = 1;&lt;br /&gt;
int allTankards = 10;&lt;br /&gt;
do {&lt;br /&gt;
  System.out.println(tankard + &amp;quot; стакан помыт&amp;quot;);&lt;br /&gt;
  tankard++;&lt;br /&gt;
}&lt;br /&gt;
while (tankard &amp;lt;= allTankards);&lt;br /&gt;
System.out.println(&amp;quot;Ну вот и все стаканы помыл&amp;quot;);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Массивы ===&lt;br /&gt;
Для организации хранения однотипных данных в Java можно использовать массивы. Массивом называется структура данных, которая&lt;br /&gt;
позволяет хранить несколько значений в одной переменной (определение расплывчатое, но суть передает верно). Объявить массив можно несколькими способами, но я предпочитаю следующий как наиболее логичный:&lt;br /&gt;
&amp;lt;source lang = &amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
int[] arrayName = new int[length]&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
При этом int – это тип переменных массива, а length – его размерность (число элементов). После того, как массив создан,&lt;br /&gt;
значения всех переменных равны null.&lt;br /&gt;
&lt;br /&gt;
Многомерный массив – это обыкновенный массив, элементами которого являются массивы, причем совсем не требуется, чтобы они&lt;br /&gt;
имели одинаковую размерность, например:&lt;br /&gt;
&amp;lt;source lang = &amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
int[][] arrayName = new int[2][];&lt;br /&gt;
arrayName[0] = new int[5];&lt;br /&gt;
arrayName[1] = new int[2];&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
В некоторых задачах требуется создать массив, состоящий из произвольных чисел. Генерация произвольных чисел возможна благодаря&lt;br /&gt;
классу Random, который входит в пакет java.util. К слову, пакеты – это иерархически именованные контейнеры, применяемые для изолирования имен классов в некотором пространстве имен, то есть пакеты применяются во избежание конфликтов с именами классов.&lt;br /&gt;
&lt;br /&gt;
Подключение класса Random к программе происходит при использовании зарезервированного слова import и команды import java.util.Random; традиционно объявляемой в начале файла, содержащего разрабатываемый класс.&lt;br /&gt;
&amp;lt;source lang = &amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
import java.util.Random;&lt;br /&gt;
public class RandomGenerator {&lt;br /&gt;
  private static Random random = new Random();&lt;br /&gt;
  private int base;&lt;br /&gt;
  public RandomGenerator(int base) {&lt;br /&gt;
    this.base = base;&lt;br /&gt;
  };&lt;br /&gt;
  public RandomGenerator() {&lt;br /&gt;
    this.base = Math.abs(random.nextInt());&lt;br /&gt;
  };&lt;br /&gt;
  public int getInt(){&lt;br /&gt;
    return Math.abs(random.nextInt(this.base));&lt;br /&gt;
  };&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Далее, приведенный код позволяет сгенерировать массив псевдослучайных чисел с использованием класса RandomGenerator, код&lt;br /&gt;
которого приведен выше:&lt;br /&gt;
&amp;lt;source lang = &amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
int[] newArray = new int[100];&lt;br /&gt;
RandomGenerator currentRG = new RandomGenerator(500);&lt;br /&gt;
for (int currentNumber = 0; currentNumber &amp;lt; 100; currentNumber++) {&lt;br /&gt;
  newArray[currentNumber] = currentRG.getInt();&lt;br /&gt;
  System.out.println(&amp;quot;newArray[&amp;quot; + currentNumber + &amp;quot;] = &amp;quot; + newArray[currentNumber]);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Иногда невозможно установить точное количество элементов в массиве, в таком случае на помощь приходят динамические массивы ArrayList. ArrayList – это класс, который входит в Collection API. Объекты, созданные на основе ArrayList, более ресурсоемки. Давайте посмотрим на работу динамических массивов на примере задачи по поиску всех простых чисел в диапазоне от 1 до N:&lt;br /&gt;
&amp;lt;source lang = &amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
private Integer[] getAllPrimeNumbers (int numberForCheck){&lt;br /&gt;
  ArrayList primeNumbers = new ArrayList();&lt;br /&gt;
  for (int currentNumber = 1; currentNumber &amp;lt;= numberForCheck; currentNumber++) {&lt;br /&gt;
    if (this.primeNumberCheckUp(currentNumber)) {&lt;br /&gt;
      primeNumbers.add(currentNumber);&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
  Integer[] result = (Integer[]) primeNumbers.toArray(new Integer[0]);&lt;br /&gt;
  return result;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
public int[] getIntArray(){&lt;br /&gt;
  Integer[] arrayOfPrimeNumbers = (Integer[]) GetAllPrimeNumder(this.number);&lt;br /&gt;
    int[] result = new int[arrayOfPrimeNumbers.length];&lt;br /&gt;
    for (int currentNumber = 0; currentNumber&amp;lt;resault.length; currentNumber++){&lt;br /&gt;
      result[currentNumber] = arrayOfPrimeNumbers[currentNumber].intValue();&lt;br /&gt;
    }&lt;br /&gt;
    return resault;&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
public Integer[] getIntegerArray(){&lt;br /&gt;
  return this.GetAllPrimeNumder(this.number);&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
В getAllPrimeNumder формируется динамический массив primeNumbers – объект класса ArrayList (для его использования необходимо подключить пакет java.util.ArrayList). Добавление нового объекта в динамический массив производится методом add(Object). После того, как динамический массив сформирован, из него извлекается простой массив методом toArray(Object[]). Обратите внимание, что из ArrayList извлекается массив объектов типа Integer, несмотря на то, что в него помещаются переменные типа int. Для получения массива состоящего из переменных типа int используется метод getIntArray().&lt;br /&gt;
&lt;br /&gt;
Динамические массивы, как правило, используют лишь до тех пор, пока не установлено точное количество элементов, т.к. скорость работы с простым массивом выше и обработка простого массива менее трудоемка.&lt;br /&gt;
&lt;br /&gt;
Для логического завершения работы с простыми числами включим ранее описанные методы (primeNumberCheckUp, getAllPrimeNumder,&lt;br /&gt;
getIntArray(), getIntegerArray()) в представленный далее класс ArrayOfPrimeNumbers.&lt;br /&gt;
&amp;lt;source lang = &amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
import java.util.ArrayList;&lt;br /&gt;
public class ArrayOfPrimeNumbers {&lt;br /&gt;
  private int number;&lt;br /&gt;
&lt;br /&gt;
  public ArrayOfPrimeNumber(int number) {&lt;br /&gt;
    this.number = number;&lt;br /&gt;
  }&lt;br /&gt;
  public int getNumber() {&lt;br /&gt;
    return number;&lt;br /&gt;
  }&lt;br /&gt;
  public void setNumber(int number) {&lt;br /&gt;
    this.number = number;&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Класс, в зависимости от вызываемого метода, возвращает массив, состоящий из элементов int или Integer.&lt;br /&gt;
&lt;br /&gt;
=== Куча хлама ===&lt;br /&gt;
Вернемся к нашей Несмеяне. Так как королевство ей досталось, прямо скажем, маленькое, пришлось ей еще и за порядком следить, что значит знать, где и что. Здесь ей помог HashMap – такая интересная структура для хранения данных, класс который входит в '''java.util.''' Экземпляры класса HashMap позволяют хранить различные именованные объекты, которые хранятся в виде пар «ключ – значение». Снаружи объекта типа HashMap нельзя узнать (как в хорошем бардаке), что же там лежит, однако, зная ключ, можно получить то, что ищешь, ну а если ключ неизвестен, то необходимо начать разбирать бардак до тех пор, пока не будет найдено то, что требуется. HashMap часто используется для хранения параметров системы. Как царевна разбирала бардак&lt;br /&gt;
мужа с помощью HashMap, можно посмотреть ниже.&lt;br /&gt;
&amp;lt;source lang = &amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
HashMap sameHeap = new HashMap();&lt;br /&gt;
sameHeap.put(&amp;quot;Key1&amp;quot;, &amp;quot;Левый носок&amp;quot;);&lt;br /&gt;
sameHeap.put(&amp;quot;Key2&amp;quot;, &amp;quot;Грязная футболка&amp;quot;);&lt;br /&gt;
sameHeap.put(&amp;quot;Key3&amp;quot;, &amp;quot;Правый носок&amp;quot;);&lt;br /&gt;
String sameObj = (String) sameHeap.get(&amp;quot;Key1&amp;quot;);&lt;br /&gt;
System.out.println(&amp;quot;Key1 = &amp;quot; + sameObj);&lt;br /&gt;
Map.Entry entry = null;&lt;br /&gt;
Iterator it = sameHeap.entrySet().iterator();&lt;br /&gt;
while (it.hasNext()) {&lt;br /&gt;
  entry = (Map.Entry) it.next();&lt;br /&gt;
  System.out.println(&amp;quot;For key = &amp;quot; + entry.getKey() + &amp;quot; value = &amp;quot; + entry.getValue());&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Для компиляции понадобится подключить java.util.HashMap, java.util.Iterator, java.util.Map – это можно сделать с помощью всего одной строкой вместо трех – import java.util.*;.&lt;br /&gt;
&lt;br /&gt;
Как вы можете убедиться, для помещения объекта в HashMap необходимо использовать метод put, где первым параметром будет ключ, а&lt;br /&gt;
вторым – ассоциируемый с ним объект. Извлечение объекта возможно с помощью метода get при передаче ключа или с помощью последовательного перебора записей в HashMap.&lt;br /&gt;
&lt;br /&gt;
После выполнения кода вы можете увидеть, что элементы в куче лежат не в том порядке, в котором вы их туда кинули (как в жизни, и не только короля). Порядок элементов в коллекции также может меняться во времени. HashMap обеспечивает постоянное время доступа для операций put и get. Как для ключей, так и для элементов допускаются значения типа null.&lt;br /&gt;
&lt;br /&gt;
=== Пятый угол ===&lt;br /&gt;
В хорошо написанной программе, как и в сказочном королевстве, все должно идти своим чередом, но непредвиденные ситуации все равно бывают, так как программа соприкасается с внешним миром (другими программами, файлами, пользователями). Для решения непредвиденных ситуаций в Java существуют исключения и специальные операторы позволяющие отловить и обработать их.&lt;br /&gt;
&amp;lt;source lang = &amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
try{&lt;br /&gt;
  // небезопасный код&lt;br /&gt;
} catch(Exception e) {&lt;br /&gt;
  // обработка исключительной ситуации&lt;br /&gt;
} finally {&lt;br /&gt;
  // гарантированно выполняющийся блок&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Выше представлена структура, с помощью которой производится обработка исключительных ситуаций: в блоке try производятся &lt;br /&gt;
потенциально опасные операции, а в блоке catch производится обработка возникшего исключения (блоков catch может быть несколько). Под блоком подразумевается последовательность операторов, объявлений локальных классов или локальных переменных, заключенных в фигурные скобки. Область видимости локальных переменных и классов ограничена блоком, в котором они определены.&lt;br /&gt;
&lt;br /&gt;
Иногда дополнительно, вне зависимости от того, как будет выполнен блок try, необходимо, чтобы выполнились какие-либо действия&lt;br /&gt;
(например, освобождение ресурсов), тогда используют оператор finally, который обеспечивает гарантированное выполнение указанного блока операторов.&lt;br /&gt;
&lt;br /&gt;
Исключительная ситуация может быть сгенерирована виртуальной машиной Java, а также программистом. Исключение &amp;quot;выбрасывается&amp;quot;&lt;br /&gt;
с помощью оператора throw.&lt;br /&gt;
&amp;lt;source lang = &amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
public float calculate(int sameA, int sameB) throws Exception {&lt;br /&gt;
  float result;&lt;br /&gt;
  if (sameB != 0) {&lt;br /&gt;
    result = sameA / sameB;&lt;br /&gt;
  } else&lt;br /&gt;
    throw new Exception(&amp;quot;Параметр для вычисления не должен быть равным нулю&amp;quot;);&lt;br /&gt;
  return result;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Предложенный метод обеспечивает деление, а так как Царевна и король никогда не делят на ноль, они все делят поровну, то с помощью оператора throw порождается исключение в случае неправильно введенных данных. Это исключение можно «отловить» с помощью catch по месту использования метода.&lt;br /&gt;
&lt;br /&gt;
Жизнь царевны и короля изменилась: пришлось осваивать азы науки и знакомиться с простыми типами (чисел), разбираться в ветвлениях налогового кодекса, использовать все три типа циклов, а также усвоить исключения. Оставим их осмыслять все это до следующего номера...&lt;/div&gt;</summary>
		<author><name>Skryabin yuri</name></author>	</entry>

	<entry>
		<id>http://wiki.linuxformat.ru/wiki/LXF84:Java</id>
		<title>LXF84:Java</title>
		<link rel="alternate" type="text/html" href="http://wiki.linuxformat.ru/wiki/LXF84:Java"/>
				<updated>2008-03-13T09:26:20Z</updated>
		
		<summary type="html">&lt;p&gt;Skryabin yuri: Содержание&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=== Сказка Java ===&lt;br /&gt;
''ЧАСТЬ 1: От кофеварок до промышленных серверов и биллинговых систем - Java можно встретить буквально везде. Начните изучение этой технологии вместе с '''Антоном Черноусовым'''.''&lt;br /&gt;
&lt;br /&gt;
Начиная ряд статей о программировании на объектно-ориентированном языке Java, хотел бы выразить свое мнение относительно корпоративного рынка разработки программного обеспечения, на котором в данный момент борются за лидерство два гиганта, две платформы: J2EE и .NET.&lt;br /&gt;
&lt;br /&gt;
В основе платформы J2EE лежит язык программирования Java – приложения, созданные с его помощью, являются кроссплатформенными, сам язык, средства разработки и технология активно поддерживаются многими корпорациями: Sun, Google, IBM, Oracle, BEA. Платформа пользуется большой популярностью и среди компаний, ориентированных на OpenSource, таких как Apache Foundation. В противовес J2EE, корпорация Microsoft предлагает свою технологию .NET, которая является колоссом, построенным на мощи программного обеспечения Microsoft.&lt;br /&gt;
&lt;br /&gt;
Сегодня еще нельзя сказать, какая технология станет доминирующей, и, возможно, от вас зависит скорость распространения современной кроссплатформенной технологии создания приложений J2EE и языка программирования Java.&lt;br /&gt;
&lt;br /&gt;
Предложенные вашему вниманию уроки позволят овладеть основными понятиями ООЯ Java и создавать различные приложения с его помощью. Рассмотрев основы языка, мы сможем изучить типовые решения (паттерны) в программировании и приступить к изучению J2EE.&lt;br /&gt;
В первом уроке мы создадим свое первое приложение и разберемся с основными понятиями: инкапсуляция, наследование и полиморфизм. Для выполнения этого урока нам понадобится пакет Java SDK 1.5, текстовый редактор и немного терпения.&lt;br /&gt;
=== Героический объект ===&lt;br /&gt;
Приступая к этой серии материалов, я вспомнил, что, как правило, изучение языков программирования начинается с написания приложения &amp;quot;Hello World!&amp;quot;, но такой прием настолько изъезжен, что я намереваюсь предложить пример поинтереснее: мы напишем приложение, рассказывающее сказку. Основа приложения – два класса. Каждый класс содержит члены двух видов: атрибуты и методы. Атрибуты – это данные, принадлежащие самому классу. Совокупное значение атрибутов определяет состояние объекта или класса. Метод – это последовательность операторов, изменяющих значения атрибутов и, как следствие, состояние класса или объекта.&lt;br /&gt;
&lt;br /&gt;
В каждой интересной сказке должен быть свой герой. Предлагаю взглянуть на класс, который реализует нашего героя. Итак, по порядку. Следующий код необходимо сохранить в файл '''FirstHero.java.'''&lt;br /&gt;
&amp;lt;source lang = &amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
public class FirstHero {&lt;br /&gt;
  private String quest;&lt;br /&gt;
  public FirstHero(String Quest) {&lt;br /&gt;
    this.quest = Quest;&lt;br /&gt;
  }&lt;br /&gt;
  public void setQuest(String Quest){&lt;br /&gt;
    this.quest = Quest;&lt;br /&gt;
  };&lt;br /&gt;
  public String getQuest(){&lt;br /&gt;
    return quest;&lt;br /&gt;
  };&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Расположение одного класса в одном файле считается хорошим тоном среди программистов на Java – так что приучайтесь к нему сразу. Имя файла должно совпадать с названием класса, расширение у файла – '''.java.'''&lt;br /&gt;
&lt;br /&gt;
Первый созданный нами класс содержит один защищенный атрибут (private – модификатор, зарезервированное слово, которое обеспечивает возможность обращения к члену класса только внутри класса) и три открытых метода (public – модификатор, зарезервированное слово, которое обеспечивает возможность обращения к члену класса из любого другого класса.). Хорошо спроектированный класс не имеет открытых атрибутов, что позволяет быть уверенным в правильной работе с ними. Доступ к защищенным атрибутам осуществляется через открытые методы. Такая организация класса позволяет разработчику через методы реализовать различные проверки и исключить неправильное поведение объекта. Класс представляет собой объединение атрибутов и методов в единое целое – подобное объединение называется инкапсуляцией.&lt;br /&gt;
&lt;br /&gt;
Вы можете заметить, что первый метод (третья строка представленного ранее листинга) имеет то же название, что и класс – FirstHero. Такой метод называется конструктором. Конструктор – это метод, который используется при создании экземпляра класса для задания внутреннего состояния объекта, например:&lt;br /&gt;
&amp;lt;source lang = &amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
FirstHero ourNewHero = new FirstHero(&amp;quot;Спасти царевну&amp;quot;);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Единственный атрибут нашего класса quest имеет тип строка (String). Для установки значения атрибута quest используется метод&lt;br /&gt;
setQuest. Метод setQuest является public и не возвращает никакого значения. Для обозначения методов, не возвращающих значение, используется зарезервированное слово void. Для вызова метода setQuest необходим обязательный параметр: Quest типа String. Для получения значения атрибута quest используется метод getQuest, который вызывается без параметров, является открытым и возвращает значение типа String.&lt;br /&gt;
&lt;br /&gt;
Вызов описанных выше методов для объекта ourNewHero осуществляется следующим образом:&lt;br /&gt;
&amp;lt;source lang = &amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
ourNewHero.getQuest();&lt;br /&gt;
ourNewHero.setQuest(&amp;quot;какая-то строка&amp;quot;);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Парные методы, различающиеся приставками set и get, принято создавать для работы с закрытыми атрибутами. Это обязательное&lt;br /&gt;
условие для реализации объекта в виде JavaBean. Что такое JavaBean, мы обсудим позже – сейчас запомните, что такое наименование методов позволяет избавиться от ряда проблем в больших системах.&lt;br /&gt;
&lt;br /&gt;
Приступим к написанию самой сказки. Возьмите следующий код и поместите его в файл '''Story.java'''.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang = &amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
public class Story {&lt;br /&gt;
  public static void main(String[] args) {&lt;br /&gt;
    FirstHero ourNewHero = new FirstHero(&amp;quot;Спасти царевну &amp;quot;);&lt;br /&gt;
    System.out.println(“Наш герой хочет отправиться в путь и “ + ourNewHero.getQuest());&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Это класс Story, он имеет всего один метод main, который является статичным (static-методы и переменные принято называть переменными класса и методами класса, т.к. они общие для всех объектов) и используется для работы с классом в целом. Метод main – это стартовая точка для запуска программы, с которой начинается интерпретация кода.&lt;br /&gt;
&lt;br /&gt;
В ходе интерпретации метода main создается новый объект ourNewHero, а также вызывается метод println объекта out, который обеспечивает вывод в стандартный выходной поток строковойпеременной.&lt;br /&gt;
&lt;br /&gt;
Откомпилируем код и увидим, что у нас получилось. Для компиляции переместитесь в каталог, где вы разместили свои файлы и выполните следующую команду:&lt;br /&gt;
&amp;lt;source lang = &amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
# javac *.java&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
При желании вы можете откомпилировать классы по отдельности, следующим образом:&lt;br /&gt;
&amp;lt;source lang = &amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
# javac Story.java&lt;br /&gt;
# javac FirstHero.java&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
В итоге вы получите два файла '''Story.class''' и '''FirstHero.class'''. Теперь посмотрим на результат:&lt;br /&gt;
&amp;lt;source lang = &amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
# java Story&lt;br /&gt;
Наш герой хочет отправиться в квест и Спасти царевну&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Первая программа на Java готова и работает! Вы создали два класса и научились выводить информацию в консоль. Но мы забыли о&lt;br /&gt;
комментариях...&lt;br /&gt;
&lt;br /&gt;
Комментарии бывают нескольких типов:&lt;br /&gt;
*Строчные начинаются с символа // и длятся до окончания строки.&lt;br /&gt;
*Многострочные комментарии заключаются между /* и */.&lt;br /&gt;
*Комментарии JavaDoc – это многострочные комментарии, заключенные между /** и */, например:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang = &amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
 * Класс является прототипом объекта &amp;quot;герой&amp;quot;&lt;br /&gt;
 * @author Chernousov Anton&lt;br /&gt;
 * @version 0.1&lt;br /&gt;
 */&lt;br /&gt;
public class FirstHero {&lt;br /&gt;
…&lt;br /&gt;
/**&lt;br /&gt;
   * Метод предназначен для установки внутренней переменной&lt;br /&gt;
quest&lt;br /&gt;
   * в значение Quest.&lt;br /&gt;
   * У этого метода один параметр&lt;br /&gt;
   * @param Quest это переменная означает задание для Героя&lt;br /&gt;
   */&lt;br /&gt;
  public void setQuest(String Quest)&lt;br /&gt;
…&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Комментарии JavaDoc предназначены для формирования документации к проекту из исходных кодов. Если добавить в файл '''FirstHero.java''' только что приведенные строки, то с помощью команды '''javadoc -author -version *.java''' можно сформировать документацию к нашему проекту.&lt;br /&gt;
&lt;br /&gt;
JavaDoc позволяет создавать подробную документацию, которая просто необходима для любого достаточно крупного проекта.&lt;br /&gt;
=== Наследование, интерфейсы и их реализация ===&lt;br /&gt;
Наша сказка написана, но что делать, если проект большой и над ним работает много людей? Как реализовать одновременное программирование разных классов так, чтобы результаты, полученные отдельными разработчиками, можно было без труда соединить в единое целое? Для решения этой задачи, а также задачи множественного наследования в Java существуют интерфейсы – interface. Но обо всем по порядку.&lt;br /&gt;
&lt;br /&gt;
Наследование – это одна из парадигм программирования, которая связана с инкапсуляцией. Суть наследования заключается в следующем: если есть класс, инкапсулирующий в себе некоторые атрибуты и методы, то класс, наследующий его, автоматически наследует все его атрибуты и методы.&lt;br /&gt;
&amp;lt;source lang = &amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
public class SecondHero extends FirstHero{&lt;br /&gt;
  public SecondHero(String Quest) {&lt;br /&gt;
    super(Quest + &amp;quot; Несмеяну&amp;quot;);&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Расположенный выше код объявляет класс SecondHero, который с помощью зарезервированного слова extends наследует (расширяет) класс FirstHero. В Java класс может наследовать (расширять)только один класс. При наследовании класса FirstHero, содержащего&lt;br /&gt;
конструктор, обязательно требуется переопределить его (например, как это делается в методе SecondHero). При выполнении оператора super(Quest) будет вызван аналогичный метод из суперкласса (класс-родителя). Строкой super(Quest + “Несмеяну”) мы переопределяем поведение конструктора. Естественно, класс SecondHero может содержать новые атрибуты и методы.&lt;br /&gt;
&lt;br /&gt;
Для проверки механизма наследования сохраните приведенный текст класса SecondHero в файл '''SecondHero.java''' и в файле '''Story.java''' измените имя класса FirstHero на SecondHero. Откомпилируйте и запустите программу, в результате вы должны увидеть следующее:&lt;br /&gt;
&amp;lt;source lang = &amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
# java Story&lt;br /&gt;
Наш герой хочет отправиться в путь и Спасти царевну Несмеяну&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
При разработке программы, перед тем, как приступить к программированию, сначала проводится процесс проектирования (например, через UML-нотации). В результате проектирования появляется документация к проекту, а также спецификации классов. Интерфейс – это явно указанная спецификация набора методов, которые должны быть представлены в классе, реализующий эту спецификацию. В серьезном проекте на момент начала программирования перед программистом оказываются интерфейсы, которые он должен реализовать в классах.&lt;br /&gt;
&lt;br /&gt;
Интерфейс в Java – это специальный класс, в котором отсутствует реализация! Давайте напишем интерфейс для нашего класса FirstHero. Следует скопировать следующий далее код и поместить его в файл '''Hero.java''' – именно этот интерфейс мы будет использован далее. Как вы видите, в отличие от других классов, интерфейс объявляется с помощью зарезервированного слова interface. В нашем случае интерфейс представляет собой следующий набор методов:&lt;br /&gt;
&amp;lt;source lang = &amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
public interface Hero {&lt;br /&gt;
  public void setQuest(String Quest);&lt;br /&gt;
  public String getQuest();&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Чтобы класс FirstHero реализовывал интерфейс Hero, необходимо изменить первую строчку в файле '''FirstHero.java''' на public class FirstHero implements Hero {. Интерфейс может наследовать (расширять) множество других интерфейсов. Наример:&lt;br /&gt;
&amp;lt;source lang = &amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
public interface Lord {&lt;br /&gt;
  public String sendToQuest();&lt;br /&gt;
  public void setBodyguard(Hero hisHero);&lt;br /&gt;
  public Hero getBodyguard();&lt;br /&gt;
}&lt;br /&gt;
 &lt;br /&gt;
public interface King extends Hero, Lord{&lt;br /&gt;
  public void setWife (String PrincesName);&lt;br /&gt;
  public String getWife();&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Класс может одновременно наследовать класс и реализовывать один или несколько интерфейсов. Например, как в классе LandLord,&lt;br /&gt;
который наследует класс FirstHero и реализует интерфейс Lord:&lt;br /&gt;
&amp;lt;source lang = &amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
public class LandLord extends FirstHero implements Lord{&lt;br /&gt;
  private Hero bodyguard;&lt;br /&gt;
  public LandLord(String Quest, Hero hisHero) {&lt;br /&gt;
    super(Quest);&lt;br /&gt;
    this.bodyguard = hisHero;&lt;br /&gt;
  }&lt;br /&gt;
  public String sendToQuest() {&lt;br /&gt;
    bodyguard.setQuest(this.getQuest());&lt;br /&gt;
    return null;&lt;br /&gt;
  }&lt;br /&gt;
  public void setBodyguard(Hero hisHero) {&lt;br /&gt;
    this.bodyguard = hisHero;&lt;br /&gt;
  }&lt;br /&gt;
  public Hero getBodyguard() {&lt;br /&gt;
    return bodyguard;&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Чтобы окончательно закрыть тему наследования, необходимо поговорить про абстрактные классы – те, что занимают промежуточное&lt;br /&gt;
место между интерфейсами и реальными классами. Объявление абстрактного класса или метода выполняется с помощью специального&lt;br /&gt;
слова abstract:&lt;br /&gt;
&amp;lt;source lang = &amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
abstract public class Knight&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Абстрактный класс представляет собой неполную реализацию всех объявленных методов, и его можно наследовать, как и любой из классов. Обязательным условием при наследовании является полная реализация абстрактных методов.&lt;br /&gt;
&lt;br /&gt;
=== Полиморфизм ===&lt;br /&gt;
Полиморфизм – это концепция, реализованная в Java, которая позволяет одному и тому же объекту выступать в разных формах. Например, экземпляр класс LandLord можно использовать как объект класса FirstHero. Это стало возможным благодаря тому, что класс LandLord наследует класса FirstHero.&lt;br /&gt;
&lt;br /&gt;
=== Перегруженные методы ===&lt;br /&gt;
Иногда при создании сложных (и не очень) систем есть необходимость реализовать два различных метода, названых одинаково – это возможно с помощью перегруженных (overloading) методов. Выбор реализации зависит от типа объектов, переданных в качестве параметров.&lt;br /&gt;
&amp;lt;source lang = &amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
public class GreatKing extends LandLord implements King{&lt;br /&gt;
  private String wife;&lt;br /&gt;
  private boolean theftedWife;&lt;br /&gt;
&lt;br /&gt;
  public GreatKing(String Quest, Hero hisHero) {&lt;br /&gt;
    super(Quest, hisHero);&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  public void setWife(String PrincesName) {&lt;br /&gt;
    this.wife = PrincesName;&lt;br /&gt;
    this.theftedWife = false;&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  public String getWife() {&lt;br /&gt;
    if (theftedWife){return null;}&lt;br /&gt;
    else{ return wife;}&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  public String getWife(boolean flag) {&lt;br /&gt;
    if (flag){ this.theftedWife = true;}&lt;br /&gt;
    return wife;&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
В представленном классе GreatKing существуют две реализации перезагруженного метода getWife, которые можно вызвать следующим образом:&lt;br /&gt;
&amp;lt;source lang = &amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
GreatKing ourKing = new GreatKing(&amp;quot;Править мудро&amp;quot;, (Hero) new FirstHero(&amp;quot;Охранять господина&amp;quot;));&lt;br /&gt;
String hisWife = ourKing.getWife();&lt;br /&gt;
String theftedHisWife = ourKing.getWife(true);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Вместо заключения ===&lt;br /&gt;
Ну вот, мы создали всех героев. Разместите интерфейсы Lord, King, а также классы LandLord и GreatKing в соответствующих файлах.&lt;br /&gt;
Немного измените класс Story, чтобы завершить сказку:&lt;br /&gt;
&amp;lt;source lang = &amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
public class Story {&lt;br /&gt;
  public static void main(String[] args) {&lt;br /&gt;
    // создадим наших героев&lt;br /&gt;
    Hero ourNewHero = (Hero) new FirstHero(&amp;quot;Спасити царевну&amp;quot;);&lt;br /&gt;
    GreatKing ourKing = new GreatKing(&amp;quot;Править мудро&amp;quot;, (Hero) new FirstHero(&amp;quot;Охранять господина&amp;quot;));&lt;br /&gt;
    LandLord ourNewLandLord = new LandLord(&amp;quot;Похитить царевну&amp;quot;, (Hero) new FirstHero(&amp;quot;Охранять господина&amp;quot;));&lt;br /&gt;
    // Женим нашего короля&lt;br /&gt;
    ourKing.setWife(&amp;quot;Несмеяна&amp;quot;);&lt;br /&gt;
    // И начнем повествование&lt;br /&gt;
    System.out.println(&amp;quot;Жил был мудрый король, и должен был он &amp;quot; + ourKing.getQuest());&lt;br /&gt;
    System.out.println(&amp;quot;Была у него жена, и звали ее &amp;quot; + ourKing.getWife());&lt;br /&gt;
    System.out.println(&amp;quot;Был в королевстве коварный Визирь и хотел он &amp;quot; + ourNewLandLord.getQuest());&lt;br /&gt;
    System.out.println(&amp;quot;И сделал это&amp;quot;);&lt;br /&gt;
    String wife = ourKing.getWife(true);&lt;br /&gt;
    //&lt;br /&gt;
    System.out.println(&amp;quot;А наш герой жаждал &amp;quot; + ourNewHero.getQuest() + &amp;quot; ..и добился этого&amp;quot;);&lt;br /&gt;
    ourKing.setWife(wife);&lt;br /&gt;
    System.out.println(&amp;quot;Король был счастлив.&amp;quot;);&lt;br /&gt;
    System.out.println(&amp;quot;Ну а что случилось дальше вы можете придумать сами...&amp;quot;);&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Откомпилируйте и насладитесь результатом выполнения урока.&lt;br /&gt;
&lt;br /&gt;
В следующей статье мы поговорим о простых числах и других типах, вычислениях, циклах, массивах и списках.&lt;/div&gt;</summary>
		<author><name>Skryabin yuri</name></author>	</entry>

	<entry>
		<id>http://wiki.linuxformat.ru/wiki/LXF86:Java</id>
		<title>LXF86:Java</title>
		<link rel="alternate" type="text/html" href="http://wiki.linuxformat.ru/wiki/LXF86:Java"/>
				<updated>2008-03-13T09:21:48Z</updated>
		
		<summary type="html">&lt;p&gt;Skryabin yuri: Начало, содержание&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=== Хранение данных ===&lt;br /&gt;
''ЧАСТЬ 3: Даже самой замечательной программе надо откуда-то черпать данные для своей работы. Данные, как известно, хранятся в файлах. Тему продолжает '''Антон Черноусов'''.''&lt;br /&gt;
&lt;br /&gt;
В предыдущей статье из цикла, посвященного программированию на Java, были рассмотрены вопросы организации простых вычислений, ветвлений, циклов, а также генерации и обработки исключений.&lt;br /&gt;
&lt;br /&gt;
В течение третьего урока мы поговорим о работе с файлами, о протоколировании работы программы и коснемся методов работы с&lt;br /&gt;
XML-данными.&lt;br /&gt;
&lt;br /&gt;
=== Файлы — потоки ===&lt;br /&gt;
&lt;br /&gt;
=== Чтение данных ===&lt;br /&gt;
&lt;br /&gt;
=== Запись данных ===&lt;br /&gt;
&lt;br /&gt;
=== Свободный доступ ===&lt;br /&gt;
&lt;br /&gt;
=== Протоколирование работы программы ===&lt;br /&gt;
&lt;br /&gt;
=== Документы XML ===&lt;br /&gt;
&lt;br /&gt;
=== Создание XML-документа ===&lt;br /&gt;
&lt;br /&gt;
=== Сохранение XML-документа ===&lt;br /&gt;
&lt;br /&gt;
=== Загрузка XML-документа ===&lt;br /&gt;
&lt;br /&gt;
=== Извлечение данных из XML-документа ===&lt;/div&gt;</summary>
		<author><name>Skryabin yuri</name></author>	</entry>

	<entry>
		<id>http://wiki.linuxformat.ru/wiki/LXF86:Java</id>
		<title>LXF86:Java</title>
		<link rel="alternate" type="text/html" href="http://wiki.linuxformat.ru/wiki/LXF86:Java"/>
				<updated>2008-03-13T09:03:16Z</updated>
		
		<summary type="html">&lt;p&gt;Skryabin yuri: Начало, содержание&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Хранение данных ==&lt;br /&gt;
''ЧАСТЬ 3: Даже самой замечательной программе надо откуда-то черпать данные для своей работы. Данные, как известно, хранятся в файлах. Тему продолжает '''Антон Черноусов'''.''&lt;br /&gt;
&lt;br /&gt;
В предыдущей статье из цикла, посвященного программированию на Java, были рассмотрены вопросы организации простых вычислений, ветвлений, циклов, а также генерации и обработки исключений.&lt;br /&gt;
&lt;br /&gt;
В течение третьего урока мы поговорим о работе с файлами, о протоколировании работы программы и коснемся методов работы с&lt;br /&gt;
XML-данными.&lt;br /&gt;
&lt;br /&gt;
=== Файлы — потоки ===&lt;br /&gt;
&lt;br /&gt;
=== Чтение данных ===&lt;br /&gt;
&lt;br /&gt;
=== Запись данных ===&lt;br /&gt;
&lt;br /&gt;
=== Свободный доступ ===&lt;br /&gt;
&lt;br /&gt;
=== Протоколирование работы программы ===&lt;br /&gt;
&lt;br /&gt;
=== Документы XML ===&lt;br /&gt;
&lt;br /&gt;
=== Создание XML-документа ===&lt;br /&gt;
&lt;br /&gt;
=== Сохранение XML-документа ===&lt;br /&gt;
&lt;br /&gt;
=== Загрузка XML-документа ===&lt;br /&gt;
&lt;br /&gt;
=== Извлечение данных из XML-документа ===&lt;/div&gt;</summary>
		<author><name>Skryabin yuri</name></author>	</entry>

	</feed>