Показать сообщение отдельно

  #5  
Старый 22.02.2016, 23:15
gattsu
Участник форума
Регистрация: 24.11.2015
Сообщений: 165
С нами: 5509192

Репутация: 1457
По умолчанию

"Один актор не является актором. Актор является частью системы акторов"

Рассмотри простой пример двух акторов.

У нас, есть два актора Ping и Pong. Акторы, с задержкой в одну секунду, пересылаю друг другу сообщения. Актор Ping отправляет строку "ping" актору Pong. Получив строку, Pong отображает её и отправляет строку "pong". Получив сообщение актор отображает строку и отправляет сообщение "ping". Этот процесс происходит до выхода из программы, пользователем.

Точка входа в модель

Код:


Код:
public static void main(String...args) {
        ActorSystem.launch(system -> {
           system.create(Ping.class, "ping", system.create(Pong.class, "pong"));
        });
}
В данному участке кода, запуск производится через статический метод ActorSystem.launch. Методом лябда выражения, в языке java, мы создает Consumer и передаем его методу launch. system - корневой актор.

Производим создание актора Pong

Код:


Код:
system.create(Pong.class, "pong")
Данный метод create, c двумя аргументами, принимает два значения.

Первый аргумент типа Сlass, передается класс который наследует BaseActor, в нашем случае Pong.class

Второй аргумент типа String - уникальное имя актора в узле. "pong"

Производим создание актора Ping

Код:


Код:
system.create(Ping.class, "ping", system.create(Pong.class, "pong"))
В данном случае вызывается перегруженный метод create(Class clazz, String name, Object...args);

Первые два аргумента являются идентичными, а в третий передается массив аргументов(синтаксический сахар vargs, Object...arss эквивалентно записи Object[] args). Система произведет поиск соответствующего конструктора, с заданными аргументами. В нашем случае будет вызван конструктор, для класса Ping

Код:


Код:
public Ping(Actor actor) {
    pong = actor;
}
так как метод create, возвращает ссылку на запись актора, которая наследует базовый абстрактный класс Actor. Таким образом мы скрываем реализацию, и защищаем классы от внешних изменений.

Другой вариант записи

Код:


Код:
public static void main(String...args) {
        ActorSystem.launch(new Consumer() {
            @Override
            public void accept(Actor system) {
                Actor pong = system.create(Pong.class, "pong");
                Actor ping = system.create(Ping.class, "ping", pong);
            }
        });
    }
Каждый актор обладает заданным поведение. Чтобы назначить поведение актору, мы сначала его создаем через метод behavior() анонимное, или поведение которое можно назначить по ключу behavior(Object key). Данные два метода возвращают класс который наследует интерфейс Actor.IBehavior. Создав поведение, через метод behavior, который вернул класс поведения, мы можем назначить ему случай поведения на указанный тип, через мето Case(Consumer consumer, Class type);

consumer - функция поведения для указанного типа, она вызывается в случае, когда актор получает соответсвующий тип сообщения

type - класс типа

T - тип значения

Код:


Код:
IBehavior behavior = behavior();
behavior.Case(value -> {
...произвести действия
}, Integer.class);
become(behavior);
Мы задали поведение, условному актору, который реагирует на входящее сообщения, числового типа, и производит какие-то вычисления.

В нашем примере поведение двух акторов выглядим следующим образом

Дла актора Pong

Код:


Код:
public static class Pong extends BaseActor {
        {
            become(
                behavior().
                    Case(
                        value -> {
                            System.out.println(value);
                            sender().send("pong", 1000);
                        },
                        String.class
                    )
            );
        }
    }
Метод sender() Возращает актора, который отправил полученное сообщение. Метод send отправляет сообщение "pong" с задержкой в 1 секунду.

То есть, получении сообщения типа String, мы отображаем его в консоли, затем отправляем сообщению "ping", отправителю, с задержкой в одну секунду.

Для актора Ping

Код:


Код:
public static class Ping extends BaseActor {
        Actor pong;
      
        public Ping(Actor actor) {
            pong = actor;
        }
      
        {
            become(
                behavior().
                    Define(
                        d -> pong.send("ping")  
                    ).
                    Case(
                        value -> {
                            System.out.println(value);
                            pong.send("ping", 1000);
                        },
                        String.class
                    )
            );
        }
    }
В данном примере присутствует шаблонный случай Define. Его можно заменить на

Код:


Код:
behavior().
Case(
define -> {
pong.send("ping")
},
Actor.Define.class
);
Actor.Define системный класс-сообщение, которое отправляется, при создании каждому актору. Данное сообщение не обязательно для обработки.

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

В шаблонном поведении Define, мы отправляем сообщение актору pong, который передали при создании, pong.send("ping"). Это является источником вычислений в данной модели. То есть при создании актора ping мы отправляем сообщение актору pong, на что, в случае актора pong, он получает и обрабатывает сообщение, отобразив его на консоли и ответив сообщением "pong".

Результат выполнения данной программы будет, бесконечное, поочередное отображения, на консоли, строк "ping" и "pong"

Цитата:
Сообщение от Спойлер  

ping

pong

ping

pong

ping

pong

ping

pong

ping

pong

ping

pong

ping

pong

...
У меня отсутствует понятие планировки, вся планировка организовывается путем задержки сообщений.

ПС На данный момент, в этой имплементации, не реализована отправка сообщения по адресу.
 
Ответить с цитированием