Эквивалент Goroutines в Clojure/Java

Недавно мне понравилось наблюдать за разговорами Google IO о шаблонах параллельной работы Go

Хотя подход Go к параллелизму (groutines, связь по каналам) явно отличается от Clojure (неизменяемость, управляемые ссылки, STM), казалось, что подход Go может быть полезен в некоторых случаях в контексте Clojure.

Таким образом, существует прямой эквивалент в Clojure или Java для примитивов параллелизма Go (возможно, библиотеки), в частности:

  • channel -like объектов, которые блокируются до тех пор, пока читатель и писатель не будут доступны с обоих концов
  • select -like, которая может ждать результатов по нескольким каналам

PS Прекрасно доволен решением Java, поскольку он был бы легко использовать из Clojure

ОБНОВЛЕНИЕ Поскольку вопрос был первоначально задан, у Clojure теперь есть core.async, который обеспечивает все эти функции и многое другое.

Ответ 1

Вы должны проверить core.async. Это библиотека, написанная Ричем Хики, которая реализует стильные каналы.

Ответ 2

канальные объекты, которые блокируются до тех пор, пока читатель и писатель не будут доступны с обоих концов

Это немного запутанно. Вы имеете в виду "блоки, пока, если вы не пишете, читатель доступен или, если читаете, доступен писатель"? Я говорю от имени потоков, а не от конструкции, конструкция не может блокировать только потоки. (Чтобы избежать путаницы, конструктор должен проинструктировать потоки).

Если мое предположение верно, есть два варианта, которые вы можете иметь (в стандартной Java).

  1. SynchronousQueue
  2. TransferQueue (хотя это также можно использовать в качестве буферного канала)

Выборочная конструкция, которая может ждать результатов по нескольким каналам

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

Ответ 3

Недавно я написал книгу " Clojure", которая поддерживает программирование с конструкциями параллелизма Go, добавив некоторые идиомы Clojure в этот параллельный стиль программирования.

Основными конструкциями параллельного программирования Go являются:

  1. Подпрограммы
  2. Синхронные (блокирующие) каналы
  3. Ограниченные, в основном асинхронные (неблокирующие) каналы
  4. Оператор select который считывает следующее доступное сообщение из нескольких каналов
  5. Операции таймаута на канале read/write/selects

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

Я пробовал использовать lamina, но ему не хватает ограниченных каналов (которые вы можете захотеть в некоторых сценариях и являетесь частью модели канала с буферизацией), и насколько я могу сказать, что у вас нет способа создать блок производителя, когда вы отправляете сообщение на канал. Это ключевая особенность модели параллелизма Go.

Я включил ряд примеров, используя библиотеку go-lightly в git repo. Большинство из них основано на примерах, которые Роб Пайк дал на переговорах в течение последних двух лет.

Было бы интересно построить библиотеку Clojure поверх JCSP, но я еще не исследовал ее.

Ответ 4

Не зная ничего о Go, взгляните на Lamina, чтобы узнать, подходит ли она тому, что вы ищете https://github.com/ztellman/lamina

Ответ 5

Вы можете посмотреть на Квасар/Пульсар. Это очень новое, но это именно то, что вы ищете.

Ответ 6

Взгляните на Джокса. Это похожий на Clojure диалект Lisp, ориентированный на Erlang Virtual Machine.

И Erlang известен легкими суб-1000-байтными процессами.

Также Erjang несколько связан и может вас заинтересовать. Это реализация виртуальной машины Erlang поверх JVM.

Поэтому теоретически вы можете скомпилировать Joxa на BEAM, а затем запустить JVM. Не то, чтобы я рекомендовал его :-).

Ответ 8

Я очень рекомендую JCSP, основанный на алгоритмах Occam/transputer. Ключевые части этой реализации API были проверены на корректность с использованием формальных методов и формальных алгоритмов проверки, поэтому они настолько надежны, насколько это возможно (альтернативный класс является главным достижением в этом отношении).

JCSP очень хорош... однако недостатком остается ограничение, наложенное JVM, особенно высокая стоимость потоков. В Go или Occam потоки могут насчитывать миллионы, но не так на JVM.