Kurz: Erlang-Prozesse sind extrem leichtgewichtig (Hunderttausende sind normal) und teilen keinen Speicher. Sie kommunizieren per Nachricht mit ! (senden) und receive (empfangen):
Teil des Kurses Erlang
Prozesse starten und Nachrichten senden
Erlang-Prozesse sind extrem leichtgewichtig (Hunderttausende sind normal) und teilen keinen Speicher. Sie kommunizieren per Nachricht mit ! (senden) und receive (empfangen):
echo() ->
receive
{From, Nachricht} ->
From ! {echo, Nachricht},
echo();
stop ->
ok
end.
main(_) ->
Pid = spawn(fun echo/0),
Pid ! {self(), hallo},
receive
{echo, Antwort} -> io:format("Antwort: ~p~n", [Antwort])
after 1000 -> io:format("Timeout~n")
end,
Pid ! {self(), welt},
receive
{echo, A2} -> io:format("Antwort: ~p~n", [A2])
end,
Pid ! stop,
timer:sleep(50),
io:format("lebt noch: ~p~n", [is_process_alive(Pid)]).Ausgabe:
Antwort: hallo
Antwort: welt
lebt noch: falseZustand in Prozessen
Ein Prozess hält Zustand in den Argumenten seiner Schleife:
zaehler(N) ->
receive
erhoehe -> zaehler(N + 1);
{abfragen, From} -> From ! {stand, N}, zaehler(N);
stop -> ok
end.
main(_) ->
Z = spawn(fun() -> zaehler(0) end),
[Z ! erhoehe || _ <- lists:seq(1, 5)],
Z ! {abfragen, self()},
receive {stand, Stand} -> io:format("Stand: ~p~n", [Stand]) end,
Z ! stop,
Eltern = self(),
Arbeiter = [spawn(fun() -> Eltern ! {ergebnis, I, I * I} end) || I <- lists:seq(1, 5)],
Ergebnisse = [receive {ergebnis, I, Q} -> {I, Q} end || I <- lists:seq(1, length(Arbeiter))],
io:format("~p~n", [lists:sort(Ergebnisse)]),
Viele = [spawn(fun() -> receive stop -> ok end end) || _ <- lists:seq(1, 10000)],
io:format("~p Prozesse gestartet~n", [length(Viele)]),
[P ! stop || P <- Viele],
ok.Ausgabe:
Stand: 5
[{1,1},{2,4},{3,9},{4,16},{5,25}]
10000 Prozesse gestartetVerknüpfung, Monitore und Fehler
Prozesse können sich gegenseitig überwachen. Das ist die Grundlage der Fehlertoleranz:
main(_) ->
logger:set_primary_config(level, none), % Absturzberichte unterdrücken
{Pid, Ref} = spawn_monitor(fun() -> exit(kaputt) end),
receive
{'DOWN', Ref, process, Pid, Grund} -> io:format("Prozess endete: ~p~n", [Grund])
end,
process_flag(trap_exit, true),
Kind = spawn_link(fun() -> 1 / hd([0]) end),
receive
{'EXIT', Kind, {badarith, _}} -> io:format("Kind: badarith~n");
{'EXIT', Kind, Anders} -> io:format("Kind: ~p~n", [Anders])
end,
{P2, R2} = spawn_monitor(fun() -> ok end),
receive {'DOWN', R2, process, P2, normal} -> io:format("normal beendet~n") end,
register(meinprozess, spawn(fun() -> receive {Von, ping} -> Von ! pong end end)),
meinprozess ! {self(), ping},
receive pong -> io:format("pong von registriertem Namen~n") end,
io:format("~p~n", [whereis(unbekannt)]).Ausgabe:
Prozess endete: kaputt
Kind: badarith
normal beendet
pong von registriertem Namen
undefinedMerke
spawnstartet Prozesse,!sendet,receiveempfängt (mitafterals Timeout)- Prozesse teilen keinen Speicher; Zustand lebt in der Schleife des Prozesses
spawn_link,spawn_monitorundtrap_exitüberwachen andere Prozesseregister/2gibt Prozessen Namen
Übungsaufgabe
Schreibe einen Prozess, der Zahlen addiert und die Summe auf Anfrage zurückschickt.
Quiz zur Selbstkontrolle
Wie sendet man eine Nachricht?
- Pid ! Nachricht (richtig)
- send(Pid)
- Pid.send(Nachricht)
- post Pid
Was ist ein Monitor?
- Überwachung eines Prozesses mit DOWN-Nachricht (richtig)
- Ein Bildschirm
- Ein Debugger
- Ein Modul
Teilen Erlang-Prozesse Speicher?
- Nein, nur Nachrichten (richtig)
- Ja, immer
- Nur Atome
- Nur Listen
Weiter im Kurs
Zurück: Rekursion, Strings und Binaries
Weiter: OTP: gen_server und Supervisor
Alle Kapitel: Erlang im Überblick