Поддержи Openmeetings

среда, 27 октября 2010 г.

Java: параллельные коллекции

Технологии Java — явление, сопровождающее нас повсюду, где царствуют современные разработки, электронные устройства любого вида и предназначения. Проще — повсюду, где имеет место программирование, особенно программирование основных компьютеров сети — серверов. Собственно, последнее труднее всего представить сегодня без Java. Этот факт, несомненно, заслуживает того, чтобы о нём говорили много и многие.

За 15 лет своего существования Java обросла множеством деталей, которые полезно знать. Например, от современного программиста, желающего работать у одного из создателей Apache Harmony, требуется разобраться в потокобезопасности обращения к java.util.HashMap. К Вашему прочтению я предлагаю обзор современных возможностей быстрой синхронизации коллекций, которым, на мой взгляд, во всемирной паутине уделено слишком мало внимания.

Пакет java.util.concurrent

Пакет java.util.concurrent и его подпакеты добавлены в JDK*, начиная с версии 1.5. Этот пакет содержит в себе массу функциональных возможностей синхронизации параллельных потоков. Исторически, начиная с JDK 1.0, в java.util коллекции, такие как Vector и Hashtable, были явным образом синхронизованы. Сейчас, когда большинство компьютеров стало многоядерными, многих беспокоит, что во время работы одного потока с коллекцией все остальные стоят. Требование сегодняшнего дня: минимум блокировок.

Авторы JDK 1.2 отдали синхронизацию на откуп разработчикам, выбросив синхронизацию, например, из java.util.HashMap. Разработчики не всегда пользовались открывшимися возможностями грамотно, что приводило к нарушению логики работы и структуры внутренних данных коллекции. Поэтому следующей итерацией разработки стало создание пакета java.util.concurrent, содержащего классы, эффективно реализующие стандартные модели синхронизации из мира операционных систем и их приложения:

  • Исполнители
  • Очереди
  • Семафоры
  • Параллельные коллекции

Подпакеты java.util.concurrent описывают локи и атомарные операции. В этой статье ознакомимся подробнее с параллельными коллекциями. Прежде всего, нас интересуют потокобезопасные реализации интерфейсов List и Map.

ConcurrentHashMap

Данный класс обеспечивает параллельное выполнение множества операций чтения и записи. Достигается это благодаря тому, что во время выполнения перебора коллекции вся таблица не блокируется, а значит в ней остается возможность модификации данных. Таблица делится на число сегментов равное числу одновременно работающих потоков, которые записывают данные. И запись в этом сегменте не влияет на данные остальных ячеек. Итераторы, которые возвращают ConcurrentHashMap.iterator(), возвращают также каждую запись массива не больше одного раза и не выбрасывают при этом ConcurrentModificationException. Однако вместе с тем, итераторы ConcurrentHashMap не гарантируют, что новый элемент попадет в уже созданный итератор или будет удален из него при необходимости. В завершении знакомства с этим классом стоит упомянуть о такой достаточно интересной штуковине, как ReenterantReadWriteLock. С помощью неё Вы можете сделать любой объект поотокобезопасным по принципу, что чтение данных может производиться несколькими потоками без блокировки, а запись только одним.

CopyOnWriteArraySet и CopyOnWriteList

Ещё два класса в java.util.concurrent реализируют список и множество. Итераторы этих коллекций перебирают только те элементы, которые были в коллекции ещё при конструировании итератора. Данный класс предназначен для копирования внутренних данных массива при попытке их изменения. По сути, в основе CopyOnWriteArraySet лежит CopyOnWriteList с volatile ссылкой на массив. При записи создается новый массив на единицу больше текущего. Он копируется в новый и ссылка на массив обновляется. То есть, при каждом изменении списка создается его новая копия и работа идет уже в ней. Такая изменяемая ссылка на массив избавляет от необходимости всякий раз копировать список при переборе, или блокировать таблицу. Запись в массив делается с синхронизацией. Чтение записей массива выполняется без синхронизации. CopyOnWriteArrayList удобно использовать в работе со списками небольших размеров и когда число чтений в разы превышает число записей (вставок или удалений).

*Java Development Kit — инструментарий для работы с Java, включает в себя компилятор, стандартные библиотеки классов Java, утилиты, исполнительную систему JRE, документацию и примеры.

Комментариев нет :

Отправить комментарий