Давным давно, когда деревья компьютеры были большими, а процессоры одноядерными, все приложения запускались в один поток и не испытывали сложностей синхронизации. Современные же приложения стремятся использовать все имеющиеся ресурсы, в частности, все доступные CPU. К сожалению, использовать стандартные структуры данных при многопоточной обработке не представляется возможным, поэтому в Java 5 появились потокобезопасные структуры данных,
т.е. функционирующие исправно, при использовании из нескольких потоков одновременно, и расположились они в пакете java.util.concurrent. На самом деле, потокобезопасные, но неэффективные, структуры данных, как, например, Vector и Hashtable, появились еще в Java 1.0.
В настоящий момент, они не рекомендуются к использованию. Однако, не взирая на всю технологическую мощь, заложенную в пакет java.util.concurrent, обработка информации потокобезопасными коллекциями возможна лишь в рамках одного компьютера, а это порождает проблему масштабируемости.  А что если нужно, в реальном времени, обрабатывать информацию о 100 миллионах клиентов,
когда датасет занимает 100Тб, а каждую секунду нужно совершить 100+ тысяч операций?
Вряд ли это возможно, даже на самом крутом современном железе, а если и возможно — только представьте себе его стоимость! Намного дешевле добиться такой же вычислительной мощности объединив множество обычных компьютеров в кластер.  Остается лишь вопрос межкомпьютерного взаимодействия привычными средствами, схожими по API с потокобезопасными коллекциями из пакета java.util.concurrent и дающими те же гарантии, но не на одном компьютере, а на всем кластере.  Такие возможности и гарантии могут дать распределенные структуры данных. Рассмотрим некоторые из распределенных структур данных, позволяющих, без особых сложностей, сделать из многопоточного алгоритма распределенный.  Рассматриваемые в дальнейших примерах, реализации распределенных структуры данных являются частью функционала распределенного кеша Apache Ignite. IgniteAtomicReference предоставляет compare-and-set семантику. Предположим, есть 2 компьютера, связаных общей сетью. Запустим Apache Ignite на обоих (предварительно подключив библиотеки) На обоих компьютерах попробуем изменить хранимое значение Восстановим оригинальное значение IgniteAtomicLong расширяет семантику IgniteAtomicReference добавляя атомарные increment/decrement операции: Подробная документация: https://apacheignite.readme.io/docs/atomic-types Примеры на github IgniteAtomicSequence позволяет получать уникальный идентификатор, причем уникальность гарантируется в рамках всего кластера. IgniteAtomicSequence работает быстрее IgniteAtomicLong, т.к. вместо того чтобы синхронизироваться глобально на получении каждого идентификатора, получает сразу диапазон значений и, далее, выдает идентификаторы из этого диапазона. Подробная документация: https://apacheignite.readme.io/docs/id-generator
Пример на github — IgniteAtomicSequenceExample IgniteCountDownLatch позволяет синхронизировать потоки на разных компьютерах в рамках одного кластера. Запустим следующий код на 10 компьютерах одного кластера В результате, все latch.await() выполнятся гарантированно позже того, как выполнятся все десять latch.countDown(). Подробная документация: https://apacheignite.readme.io/docs/countdownlatch
Пример на github — IgniteCountDownLatchExample IgniteSemaphore позволяет лимитировать число одновременных действий в рамках одного кластера. Гарантируется, что, одновременно, не более 20 потоков, в рамках одного кластера, будут выполнять код внутри секции try. Подробная документация: https://apacheignite.readme.io/docs/distributed-semaphore
Пример на github — IgniteSemaphoreExample IgniteQueue предоставляет те же возможности, что и BlockingQueue, но в рамках целого кластера. Попытаемся получить элемент из очереди Выполнение приостановится на queue.take() до тех пор пока, в рамках того же кластера, не произойдет добавление в очередь Подробная документация: https://apacheignite.readme.io/docs/queue-and-set
Пример на github — IgniteQueueExample В связи с тем, что статья получилась исключительно обзорной, а многим, наверняка, интересно как же все это работает под капотом — в следующей статье я рассмотрю особенности реализации каждой из распределенных структур данных описанных в данной статье. Java developer