Переход с параллелизма Java на параллелизм Scala

У меня есть довольно стандартный механизм в Java для решения проблемы:

  • Рабочие элементы должны быть запланированы для выполнения в определенное время
  • Затем каждый рабочий элемент должен ожидать, когда условие станет истинным.
  • Рабочие элементы должны быть отменяемыми

Я использую следующее решение:

  1. Иметь однопоточный планировщик для планирования моих рабочих элементов
  2. Иметь ExecutorService (который может быть многопоточным)
  3. Затем каждый запланированный рабочий элемент отправляет фактическую работу в ExecutorService. Возвращенный Future кэшируется на карте. Служба завершения используется для удаления будущего из кеша, когда работа завершена.
  4. Элементы могут быть отменены через кешированные фьючерсы

Конечно, мой исполнитель должен быть не меньше ожидаемого количества блокирующих рабочих элементов, но на практике это не проблема.

Итак, теперь я пишу код на Scala и использую фреймворк акторов. Предполагая, что мой рабочий элемент может быть инкапсулирован в событие, отправленное актеру:

  1. Какой механизм я бы использовал для планирования рабочего элемента на определенное время?
  2. Если рабочий элемент — это событие, отправляемое действующему лицу, как я могу гарантировать, что пул резервных потоков больше, чем количество элементов, которые могут быть заблокированы одновременно?
  3. Как я могу отменить ранее запланированный рабочий элемент?

person oxbow_lakes    schedule 05.06.2009    source источник
comment
Можете ли вы уточнить, что означает условие, ставшее истинным? Это глобальное состояние? Это ввод-вывод?   -  person Apocalisp    schedule 05.06.2009
comment
Я просто имею в виду, что в рамках работы процесс может блокироваться при возникновении каких-либо событий (например, при получении файла).   -  person oxbow_lakes    schedule 05.06.2009


Ответы (2)


Какой механизм я бы использовал для планирования рабочего элемента на определенное время?

Я бы использовал java.util.concurrent.ScheduledExecutorService.

Если рабочий элемент — это событие, отправляемое действующему лицу, как я могу гарантировать, что пул резервных потоков больше, чем количество элементов, которые могут быть заблокированы одновременно?

Это кажется мне дизайном, который побеждает усилия по распараллеливанию. Постарайтесь свести к минимуму или устранить блокировку и глобальное состояние. Это барьеры для компонуемости и масштабируемости. Например, рассмотрите возможность создания одного выделенного потока, который ожидает поступления файлов, а затем запускает события для акторов. Или посмотрите на java.nio для асинхронного неблокирующего ввода-вывода.

Я не совсем понимаю ваши требования здесь, но кажется, что у вас может быть один поток/актер, ищущий события ввода-вывода. Затем в качестве запланированных «рабочих элементов» запланируйте эффекты, создающие неблокирующих актеров. Попросите этих акторов зарегистрироваться в потоке/актере ввода-вывода, чтобы получать сообщения о событиях ввода-вывода, которые им интересны.

Как я могу отменить ранее запланированный рабочий элемент?

ScheduledExecutorService возвращает фьючерсы. В этом отношении у вас неплохая конструкция. Соберите их на карту и вызовите future.cancel().

person Apocalisp    schedule 06.06.2009
comment
Вы совершенно правы в том, что блокирующая модель работы неуместна, и я сам пришел к такому же выводу, но откладывал полную переписку. Однако я, наконец, сделал это в пятницу, и теперь у меня гораздо лучшая система. - person oxbow_lakes; 08.06.2009

У вас может быть действующее лицо планирования со списком запланированных действующих лиц, которое использует Actor.receiveWithin(), чтобы просыпаться каждую секунду или около того и отправлять сообщения акторам, которые готовы к выполнению. Исполнитель планирования также может обрабатывать отмену. Другой вариант — позволить каждому актеру управлять своим собственным планированием напрямую с помощью receiveWithin() вместо централизованного планирования.

Эта проблема обсуждается в сообщении блога Простой cron, похожий на планировщик в Scala.

person markusk    schedule 07.06.2009