
- •Содержание
- •1. Введение
- •2. Создание и уничтожение объектов
- •3. Методы, общие для всех объектов
- •4. Классы и интерфейсы
- •5. Замена конструкций на языке c
- •6. Методы
- •7. Общие вопросы программирования
- •8. Исключения
- •9. Потоки
- •10. Сериализация
- •11. Литература
- •Глава 1
- •Глава 2 Создание и уничтожение объектов
- •Рассмотрите возможность замены конструкторов статическими методами генерации.
- •Свойство синглтона обеспечивайте закрытым конструктором
- •Отсутствие экземпляров обеспечивает закрытый конструктор
- •Не создавайте дублирующих объектов
- •Уничтожайте устаревшие ссыпки (на объекты)
- •Остерегайтесь методов flnalize
- •Глава 3 Методы, общие для всех объектов
- •Переопределяя метод equals, соблюдайте общие соглашения
- •Переопределяя метод equals, всегда переопределяйте hashCode
- •Всегда переопределяйте метод toStrlng
- •Подумайте над реализацией интерфейса ComparabIe
- •Глава 4 Классы и интерфейсы
- •Сводите к минимуму доступность классов и членов
- •Предпочитайте постоянство
- •Предпочитайте компоновку наследованию
- •Предпочитайте интерфейсы абстрактным классам.
- •Используйте интерфейсы только для определения типов
- •Предпочитайте статические классы-члены нестатическим
- •Глава 5
- •3Амена констрvкций на языке с
- •3Аменяйте структуру классом
- •3Амеияйте объедииеиие иерархией классов
- •/* Помещает данные в одно из полей объединения ... */
- •3Аменяйте конструкцию enum классом
- •Указатель на функцию заменяйте кпассом и интерфейсом
- •Глава 6 Методы
- •Проверяйте достоверность параметров
- •При необходимости создавайте резервные копии
- •Тщательно проектируйте сигнатуру метода
- •Перегружая методы, соблюдайте осторожность
- •Возвращайте массив нулевой длины, а не null
- •Для всех открытых элементов арi пишите dос - комментарии
- •Глава 7 Общие вопросы программирования
- •Сводите к минимуму область видимости локальных переменных
- •Изучите библиотеки и пользуйтесь ими
- •Не используйте строку там, где более уместен иной тип
- •При конкатенации строк опасайтесь потери производительности
- •Для ссыпки на объект используйте его интерфейс
- •Соблюдайте осторожность при использовании машинно-зависимых методов
- •Соблюдайте осторожность при оптимизации
- •Глава 8 Исключения
- •Используйте исключения лишь в исключительных ситуациях
- •Применяйте обрабатываемые исключения для восстановления, для программных ошибок используйте исключения времени выполнения
- •Избегайте ненужных обрабатываемых исключений
- •Предпочитайте стандартные исключения
- •Инициируйте исключения, соответствующие абстракции
- •Для каждого метода документируйте все инициируемые исключения
- •В описание исключения добавляйте информацию о сбое
- •Добивайтесь атомарности методов по отношению к сбоям
- •Не игнорируйте исключений
- •Глава 9 Потоки
- •Синхронизируйте доступ потоков к совместно используемым изменяемым данным
- •Избегайте избыточной синхронизации
- •Никогда не вызывайте метод wait вне цикла
- •Не попадайте в зависимость от планировщика потоков
- •При работе с потоками документируйте уровень безопасности
- •Избегайте группировки потоков
- •Глава 10 Сериализация
- •Соблюдайте осторожность при реализации интерфейса SerializabIe
- •Рассмотрите возможность использования специализированной сериализованной формы
- •Метод readObject должен создаваться с защитой
- •При необходимости создавайте метод readResolue
Избегайте группировки потоков
Помимо потоков, блокировок и мониторов, система многопоточной обработки предлагает еще одну базовую абстракцию: группа потоков (thread gгоuр). Первоначально группировка потоков рассматривалась как механизм изоляции апплетов
197
в целях безопасности. В действительности своих обязательств они так и не выполнили, а их роль в системе безопасности упала до такой степени, что в работе, где выстраивается модель безопасности для платформы Java 2 (Gong99], они даже не упоминаются.
Но если группировка потоков l:Ie несет никакой функциональной нагрузки в системе безопасности, то какие же функции она выполняет? В общих словах, она позволяет применять примитивы класса Thread сразу к целой группе потоков. Некоторые из этих примитивов уже устарели, остальные используются нечасто. В итоге группировка потоков не может дать достаточного количества полезной функциональности.
По иронии судьбы, API ThreadGroup слаб с точки зрения поддержки многопоточности. Чтобы для некоей группы получить перечень активных потоков, вы должны вызвать метод enumerate. В качестве параметра ему передается массив, достаточно большой, чтобы в него можно было записать все активные потоки. Метод activeCount возвращает количество активных потоков в группе, однако нет никакой' гарантии, что это количество не изменится в то время, пока вы создаете массив и передаете его методу enumerate. Если указанный массив окажется слишком мал, метод enumerate без каких-либо предупреждений игнорирует потоки, не поместившиеся в массив.
Точно так же API некорректен, когда ему передается список подгрупп, входящих в группу потоков. И хотя указанные проблемы можно было решить, добавив в класс ThreadGroup новые методы, этого не было сделано из-за отсутствия реальной потребности. Группировка потоков сильно устарела.
Подведем итоги. Группировка потоков практически не имеет сколь-нибудь полезной функциональности, и большинство предоставляемых ею возможностей имеет дефекты. Группировку потоков следует рассматривать как неудачный эксперимент, а существование групп можно игнорировать. Если вы проектируете класс, который работает с логическими группами потоков, вам нужно записывать ссылки Thread, соответствующие каждой логической группе, в массив или коллекцию. Вы могли заметить, что этот совет вступает в противоречие со статьей 30 "Изучите библиотеки и пользуйтесь ими". Однако в данном случае статья 30 не права.
В большинстве случаев следует игнорировать группировку потоков. Однако есть одно небольшое исключение. Нечто полезное можно найти в интерфейсе класса ThreadGroup. Когда какой-либо поток в группе инициирует исключение, не отлавливаемое в приложении, автоматически вызывается метод ThreadGroup.uncaughtException. Этот метод используется "рабочим окружением" для того, чтобы должным образом реагировать на необработанные исключения. Реализация, предлагаемая по умолчанию, печатает трассировку стека в стандартный поток сообщений об ошибках. Возможно, вы захотите поменять такую реализацию, направив, например, трассировку стека в определенный журнал регистрации.
198