Введение в программирование на Akka:

Как можно короче, давайте посмотрим, как мы разрабатываем приложения Akka.

Приложения Akka создаются в 2 простых шага.

1. Создайте протоколы сообщений.
2. Создайте актеров.

Актеры и передача сообщений:

Актер - это нить, имеющая почтовый ящик для приема сообщений.

Чтобы реализовать актера, вы создаете подкласс scala.actors.Actor и реализуете метод act.

Этот актер ничего не делает со своим почтовым ящиком. Он просто печатает сообщение пять раз и закрывается.

импортировать scala.actors._

объект SillyActor расширяет Actor {

def act () {

for (i ‹- от 1 до 5) {

println (я действую!)
Thread.sleep (1000)

}
}

}

Вы запускаете актера, вызывая его метод start, аналогично тому, как вы запускаете поток Java:

Пример выполнения:

scala ›SillyActor.start ()

Я играю!
Я играю!
Я играю!
Я играю!
Я играю!

Актеры общаются, отправляя друг другу сообщения.
Вы отправляете сообщение, используя! метод, например:

scala ›SillyActor! всем привет

Вы также можете создать актера, используя служебный метод с именем субъект в объекте scala.actors.Actor:

импортировать scala.actors.Actor._

val СерьезныйActor2 = Актер {

для (i ‹- от 1 до 5)

println (вот в чем вопрос)
Thread.sleep (1000)

}

Выполнить вывод:

scala ›Вот в чем вопрос.
Вот в чем вопрос.
Вот в чем вопрос.
Вот в чем вопрос.
Вот в чем вопрос.

Новый, более общительный актер, который ждет сообщения в своем
почтовом ящике и распечатывает все, что получает.

Он получает сообщение, вызывая receive, передавая частичную функцию.

val echoActor = Актер {

while (true) {
получить {

case msg = ›
println (полученное сообщение: + msg)

}
}

}

Когда актор отправляет сообщение, оно не блокируется, а когда актер получает сообщение, оно не прерывается. Отправленное сообщение ожидает в почтовом ящике принимающего актера, пока актер не получит его вызовов.
Вы можете увидеть это
поведение, которое проиллюстрировано здесь:

scala ›echoActor! привет
получил сообщение: привет там

scala ›echoActor! 15
scala ›получено сообщение: 15

Актер будет обрабатывать только сообщения, соответствующие одному из случаев в частичной функции, переданной для приема.
Для каждого сообщения в почтовом ящике метод receive сначала вызывает isDefinedAt для переданной частичной функции, чтобы определить, есть ли в нем регистр, который будет соответствовать и обработать сообщение.

Метод получения выберет первое сообщение в почтовом ящике, для которого isDefinedAt
вернет true, и передаст это сообщение методу apply частичной функции.
Метод apply частичной функции будет обрабатывать сообщение.

Если в почтовом ящике нет сообщения, для которого isDefinedAt возвращает true, актор, для которого был активирован прием, будет блокироваться до тех пор, пока не придет соответствующее сообщение.

Например, вот актер, который обрабатывает только сообщения типа Int:

val intActor = актер {
получить {

case x: Int = ›// Я хочу только Ints
println (Получил Int: + x)

}
}

Например, если вы отправляете String или Double, intActor игнорирует сообщение:

scala ›intActor! Привет

scala ›intActor! Math.Pi

Но если вы передадите Int, вы получите распечатанный ответ:

scala ›intActor! 12

Получил интеллект: 12

React: Повышение производительности за счет повторного использования потоков.

Чтобы помочь вам сохранить потоки, Scala предоставляет альтернативу обычному методу приема, называемому response. Как и получение, реакция выполняет частичную функцию. Однако, в отличие от приема, response не возвращается после того, как находит и обрабатывает сообщение.

Его тип результата - Ничего. Он оценивает обработчик сообщений и все.

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

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

объект NameResolver расширяет Actor {

import java.net. {InetAddress, UnknownHostException}

def act () {

react {

case (имя: Строка, актер: Актер) = ›
актер! getIp (имя)
act ()

case EXIT = ›
println (Преобразователь имен завершается.)
// завершаем работу

case msg = ›
println (Необработанное сообщение: + msg)
act ()

}

}

def getIp (name: String): Option [InetAddress] = {

попробуйте {
Some (InetAddress.getByName (name))

} поймать {

case _: UnknownHostException = ›Нет

}

}

}

Написать актеру так, чтобы он использовал реакцию вместо получения, сложно, но окупается в исполнении. Поскольку response не возвращается, стек вызовов вызывающего актора может быть отброшен, освобождая ресурсы потока для другого актора.

В крайнем случае, если все акторы программы используют реакцию, то они могут быть реализованы в одном потоке.
Этот шаблон кодирования настолько распространен среди акторов, основанных на событиях, для него есть специальная поддержка в библиотеке. .

Функция Actor.loop многократно выполняет блок кода, даже если вызовы кода реагируют.

Метод act
NameResolver можно переписать для использования цикла. Единственное отличие в поведении этого метода действия от предыдущего заключается в том, что этот метод не обрабатывает EXIT путем выхода.

Вместо этого этот субъект будет зацикливать
и вечно реагировать на сообщения.

def act () {

цикл {
реагировать {

case (имя: Строка, актер: Актер) = ›
актер! getIp (имя)

case msg = ›
println (Необработанное сообщение: + msg)

}
}

}

Вывод:

На предыдущем шаге мы сосредоточились на изучении того, как создавать акторов Akka, которые получают и обрабатывают сообщения.

Чтобы узнать, как создавать протоколы Akka для передачи сообщений Akka Actors, для этого есть сообщение.

Найдите сообщение здесь:
Сопоставление шаблонов с протоколами каналов Akka с чертами Scala и экстракторами

Спасибо!

Спасибо, что прочитали этот пост;
Пожалуйста, найдите меня в;
Twitter: Twitter.com/VakinduPhilliam
Github: Github.com/VakinduPhilliam