English | 简体中文 | 繁體中文 | Русский язык | Français | Español | Português | Deutsch | 日本語 | 한국어 | Italiano | بالعربية
La programmazione concorrente in Erlang deve seguire i seguenti principi di base o procedure.
La lista include i seguenti principi:
piD = spawn(Fun)
Creare un nuovo processo connesso a valutare Fun. Il nuovo processo esegue in parallelo con il chiamante. Un esempio è il seguente-
-module(helloworld). -export([start/0]). start() -> spawn(fun() -> server("Ciao") end). server(Messaggio) -> io:fwrite("~p",[Messaggio]).
L'output del programma sopra è -
"Ciao"
Inviare messaggi al processo utilizzando l'identificatore Pid. L'invio dei messaggi è asincrono. Il mittente non aspetta, ma continua a fare ciò che sta facendo. Il "!" è chiamato operatore di invio.
Un esempio di esempio-
-module(helloworld). -export([start/0]). start() -> Pid = spawn(fun() -> server("Ciao") end), Pid ! {ciao}. server(Messaggio) -> io:fwrite("~p",[Messaggio]).
Ricevere i messaggi già inviati al processo. Ha la seguente sintassi-
ricezione Pattern1 [quando Guard1] -> Expressions1; Pattern2 [quando Guard2] -> Espressioni2; ... Fine
Quando il messaggio raggiunge questo processo, il sistema tenta di abbinarlo a Pattern1 (potrebbe esserci un Guard 1). Se ha successo, valuta le Expressions1. Se il primo modello non corrisponde, tenta di utilizzare Pattern2, e così via. Se nessun modello corrisponde, il messaggio viene salvato per la gestione futura e il processo attende il messaggio successivo.
Il seguente programma mostra un esempio dell'intero processo che utilizza tutti e tre i comandi.
-module(helloworld). -export([loop/0, start/0]). loop() -> ricezione {rectangle, Width, Ht} -> io:fwrite("L'area del rettangolo è ~p~n", [Width * Ht]), loop(); {circle, R} -> io:fwrite("L'area del cerchio è ~p~n", [3.14159 * R * R]), loop(); Other -> io:fwrite("Unknown"), loop() fine. start() -> Pid = spawn(fun() -> loop() end), Pid ! {rectangle, 6, 10}.
Riguardo al programma sopra, è necessario notare i seguenti punti:
La funzione loop ha un ciclo di ricezione. Pertanto, quando un messaggio viene inviato, viene elaborato dal ciclo di ricezione.
Generare un nuovo processo che passerà alla funzione loop.
Inviare un messaggio al processo generato utilizzando il comando Pid! message.
L'output del programma sopra è -
L'area del rettangolo è 60
Concurrentemente, è importante determinare il numero massimo di processi permessi sul sistema. Poi, dovresti essere in grado di capire quanti processi possono essere eseguiti contemporaneamente sul sistema.
Lasciate che vi mostriamo un esempio di come determinare il numero massimo di processi eseguibili sul sistema.
-module(helloworld). -export([max/1, start/0]). max(N) -> Max = erlang:system_info(process_limit), io:format("Maximum allowed processes:~p~n", [Max]), statistics(runtime), statistics(wall_clock), L = for(1, N, fun() -> spawn(fun() -> wait() end) end), {_, Time1} = statistics(runtime), {_, Time2} = statistics(wall_clock), lists:foreach(fun(Pid) -> Pid ! die end, L), U1 = Time1 * 1000 / N, U2 = Time2 * 1000 / N, io:format("Tempo spawn processo=~p (~p) microsecondi~n", [U1, U2]). attendere() -> ricezione morire -> void fine. for(N, N, F) -> [F()]; for(I, N, F) -> [F()|for(I+1, N, F)]. start()-> max(1000), max(100000).
Sui computer con buona capacità di elaborazione, entrambe le funzioni massime menzionate sopra passano. Di seguito è riportato un esempio di output del programma sopra menzionato.
Massimo numero di processi consentiti:262144 Tempo spawn processo=47.0 (16.0) microsecondi Massimo numero di processi consentiti:262144 Processo spawn tempo=12.81 (10.15) microsecondi
A volte, la frase di ricezione potrebbe aspettare per sempre un messaggio che non apparirà mai. Questo potrebbe avere molte ragioni. Ad esempio, potrebbe esserci un errore logico nel nostro programma, o il processo che deve inviarci un messaggio potrebbe essere crollato prima di inviare il messaggio. Per evitare questo problema, possiamo aggiungere un timeout alla frase di ricezione. Questo imposterà il tempo massimo che il processo può aspettare per ricevere un messaggio.
Di seguito è riportata la sintassi della ricezione di messaggi con timeout specificato
ricezione Pattern1 [quando Guard1] -> Expressions1; Pattern2 [quando Guard2] -> Espressioni2; ... dopo Tempo -> Espressioni fine
Il caso più semplice è creare una funzione sleeper, come mostrato nel programma di seguito.
-module(helloworld). -export([sleep/1,start/0]). sleep(T) -> ricezione dopo T -> true fine. start()-> sleep(1000).
Il codice sopra menzionato si addormenterà per 1000 millisecondi prima di uscire effettivamente.
Ogni processo in Erlang ha una posta associata. Quando si invia un messaggio a questo processo, il messaggio viene messo nella posta. Il controllo di questa posta avviene solo quando il programma valuta la frase di ricezione.
Di seguito è riportata la sintassi generale della frase di ricezione selettiva.
ricezione Pattern1 [quando Guard1] -> Expressions1; Pattern2 [quando Guard1] -> Expressions1; ... dopo Tempo -> ExpressionTimeout fine
Questo è il modo in cui funziona la frase di ricezione sopra menzionata-
Quando inseriamo una dichiarazione receive, avviamo un timer (ma solo se l'espressione contiene un'unità after).
Prendere la prima mail nel mailbox e tentare di corrispondere con Pattern1, Pattern2 ecc. Se la corrispondenza è riuscita, la mail viene rimossa dal mailbox e valutata l'espressione dopo il modello.
Se nessun modello nella dichiarazione receive corrisponde alla prima mail nel mailbox, la prima mail viene rimossa dal mailbox e messa nella "coda di conservazione". Poi provare con la seconda mail nel mailbox. Ripetere questo processo fino a trovare una corrispondenza o aver controllato tutte le mail nel mailbox.
Se tutte le mail nel mailbox non corrispondono, il processo viene sospeso e riagganciato al prossimo messaggio nuovo inserito nel mailbox. Notare che quando si riceve un nuovo messaggio, le mail nella coda di conservazione non vengono riacquisite; solo il nuovo messaggio viene corrisposto.
Una volta corrisposto un messaggio, tutte le mail inserite nella coda di conservazione vengono reimpostate nell'ordine di arrivo nel mailbox. Se è stato impostato un timer, annullarlo.
Se il timer è scaduto mentre si aspettava un messaggio, valutare l'espressione ExpressionsTimeout e riporre tutte le mail salvate nell'ordine di arrivo nel mailbox.