Самый простой способ выполнить простую обработку в Scala Actor? - PullRequest
2 голосов
/ 13 октября 2009

У меня есть актер scala, который выполняет некоторую работу всякий раз, когда клиент запрашивает его. Когда и только когда ни один клиент не активен, я бы хотел, чтобы Актер выполнил некоторую фоновую обработку.

Какой самый простой способ сделать это? Я могу думать о двух подходах:

  1. Создает новую нить с тайм-аутом и периодически будит актера. Прямой подход, но я бы хотел избежать создания другого потока (чтобы избежать лишнего кода, сложности и накладных расходов).

  2. Класс Actor имеет методactWithin, который можно использовать для тайм-аута самого актера. Но в документации сказано, что метод не возвращается. Поэтому я не уверен, как его использовать.

Редактировать; уточнение:

Предположим, что фоновое задание можно разбить на более мелкие единицы, которые можно обрабатывать независимо.

Ответы [ 3 ]

6 голосов
/ 14 октября 2009

Хорошо, я вижу, что мне нужно поставить свои 2 цента. Из ответа автора, я полагаю, техника «получения приоритета» - именно то, что нужно здесь. Обсуждение можно найти в « Erlang: приоритетный вопрос получения здесь в SO ». Идея состоит в том, чтобы сначала принимать сообщения с высоким приоритетом и принимать другие сообщения только при отсутствии сообщений с высоким приоритетом.

Поскольку акторы Scala очень похожи на Эрланга, тривиальный код для реализации этого будет выглядеть так:

def act = loop {
  reactWithin(0) {
    case msg: HighPriorityMessage => // process msg
    case TIMEOUT =>
      react {
        case msg: HighPriorityMessage => // process msg
        case msg: LowPriorityMessage => // process msg
      }
  }
}

Это работает следующим образом. У актера есть почтовый ящик (очередь) с сообщениями. Аргумент receive (или receiveWithin) является частичной функцией, и библиотека Actor ищет в почтовом ящике сообщение, которое можно применить к этой частичной функции. В нашем случае это будет объект только HighPriorityMessage. Таким образом, если библиотека Actor находит такое сообщение, она применяет нашу частичную функцию, и мы обрабатываем сообщение с высоким приоритетом. В противном случае reactWithin с таймаутом 0 вызывает нашу частичную функцию с аргументом TIMEOUT, и мы сразу же пытаемся обработать любое возможное сообщение из очереди (поскольку оно ожидает сообщения, мы не можем исключить возможность получения HighPriorityMessage).

2 голосов
/ 13 октября 2009

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

import scala.actors._

object Idling

object Processor extends Actor {
  start

  import Actor._

  def act() = {
    loop {

      // here lie dragons >>>>>
      if (mailboxSize == 0) this ! Idling
      // <<<<<<

      react {
        case msg:NormalMsg => {
          // do the normal work
          reply(answer)
        }

        case Idling=> {
          // do the idle work in chunks
        }

        case msg => println("Rcvd unknown message:" + msg)
      }

    }
  }
}

Объяснение

Любой код внутри аргумента loop, но перед вызовом react, кажется, вызывается, когда субъект собирается ждать сообщения. Я отправляю Idling сообщение себе здесь. В обработчике этого сообщения я проверяю, что размер почтового ящика равен 0, прежде чем выполнять обработку.

2 голосов
/ 13 октября 2009

Похоже, проблема, которую вы описываете, не очень подходит для подсистемы актеров . Actor предназначен для последовательной обработки своей очереди сообщений:

  • Что должно произойти, если актер выполняет работу background и приходит новое задание?

Актер может узнать только об этом, если он постоянно проверяет свой mailbox, выполняя фоновую задачу. Как бы вы это реализовали (т.е. как бы вы кодировали фоновые задачи как единицу работы, чтобы субъект мог продолжать прерывать и проверять почтовый ящик)?

  • Что должно произойти, если у субъекта есть много фоновых задач в его почтовом ящике перед главной задачей?

Эти фоновые задачи отбрасываются или отправляются другому актеру? Если последнее, как вы можете предотвратить использование процессорного времени этому субъекту для выполнения задач?

В целом, это звучит гораздо больше, как если бы вам нужно было изучить какое-то программное обеспечение в стиле сетки, которое может работать в фоновом режиме (например, Data Synapse)!

...