Erlang Language
Процессы
Поиск…
Создание процессов
Мы создаем новый параллельный процесс, вызывая функцию spawn
. Функция spawn
получит в качестве параметра функцию Fun
которую процесс будет оценивать. Возвращаемое значение функции spawn
- это созданный идентификатор процесса (pid).
1> Fun = fun() -> 2+2 end.
#Fun<erl_eval.20.52032458>
2> Pid = spawn(Fun).
<0.60.0>
Вы также можете использовать spawn/3
для запуска процесса, который будет выполнять определенную функцию из модуля: spawn(Module, Function, Args)
.
Или используйте spawn/2
или spawn/4
аналогично, чтобы запустить процесс в другом узле: spawn(Node, Fun)
или spawn(Node, Module, Function, Args)
.
Передача сообщений
Два процесса erlang могут взаимодействовать друг с другом, что также известно как передача сообщений .
Эта процедура является асинхронной в том виде, в котором процесс отправки не будет остановлен после отправки сообщения.
Отправка сообщений
Это может быть достигнуто с помощью конструкции Pid ! Message
, где Pid
является допустимым идентификатором процесса (pid), а Message
- значением любого типа данных.
Каждый процесс имеет «почтовый ящик», который содержит полученные сообщения в полученном порядке. Этот «почтовый ящик» может быть опустошен с помощью встроенной функции flush/0
.
Если сообщение отправляется в не существующий процесс, сообщение будет отброшено без каких-либо ошибок!
Пример может выглядеть следующим образом: self/0
возвращает pid текущего процесса, а pid/3
создает pid.
1> Pidsh = self().
<0.32.0>
2> Pidsh ! hello.
hello
3> flush().
Shell got hello
ok
4> <0.32.0> ! hello.
* 1: syntax error before: ’<’
5> Pidsh2 = pid(0,32,0).
<0.32.0>
6> Pidsh2 ! hello2.
hello2
7> flush().
Shell got hello2
ok
Также можно отправить сообщение нескольким процессам сразу, с Pid3!Pid2!Pid1!Msg
.
Получение сообщений
Полученные сообщения могут обрабатываться с помощью конструкции receive
.
receive
Pattern1 -> exp11, .., exp1n1;
Pattern2 when Guard -> exp21, .., exp2n2;
...
Other -> exp31, .., exp3n3;
...
after Timeout -> exp41, .., exp4n4
end
Pattern
будет сравниваться с сообщениями в «почтовом ящике», начиная с первого и самого старого сообщений.
Если шаблон совпадает, совпадающее сообщение удаляется из «почтового ящика» и вычисляется тело предложения.
Также можно определить тайм-ауты с after
конструкцией.
Timeout
- это либо время ожидания в миллисекундах, либо infinity
атома.
Возвращаемое значение receive
- это последний обработанный объект предложения.
Пример (счетчик)
A (очень) простой счетчик с передачей сообщений может выглядеть следующим образом.
-module(counter0).
-export([start/0,loop/1]).
% Creating the counter process.
start() ->
spawn(counter0, loop, [0]).
% The counter loop.
loop(Val) ->
receive
increment ->
loop(Val + 1)
end.
Взаимодействие с прилавком.
1> C0 = counter0:start().
<0.39.0>
2> C0!increment.
increment
3> C0!increment.
increment
Регистрация процессов
Можно зарегистрировать процесс (pid) для глобального псевдонима.
Это может быть достигнуто с помощью функции создания в register(Alias, Pid)
, где Alias
является атомом для доступа к процессу, а Pid
- идентификатором процесса.
Псевдоним будет доступен по всему миру!
Очень просто создать общее состояние, которое обычно не является предпочтительным. ( См. Также здесь )
Можно отменить регистрацию процесса с unregister(Pid)
и получить pid из псевдонима whereis(Alias)
.
Используйте registered()
список всех зарегистрированных псевдонимов.
Пример регистрирует Atom foo для pid текущего процесса и отправляет сообщение с использованием зарегистрированного Atom.
1> register(foo, self()).
true
2> foo ! 'hello world'.
'hello world'