Kurzusok
/
Elixir
Elixir
/
Tanterv
/
Folyamatok
Fo

Folyamatok ebben a kurzusban: Elixir

5 feladat

A(z) Folyamatok fogalomról

Az Elixirben minden kód folyamatokon belül fut. Az Elixir folyamatai:

  • Nem tévesztendők össze a rendszerfolyamatokkal.
  • Könnyűsúlyúak.
  • Meghatározott felhasználási eseteik vannak. Képesek rá, hogy:
  • Teljesen normális, ha egy Elixir-alkalmazás több száz folyamatot futtat, de az is, ha egyáltalán nem hoz létre új folyamatokat, különösen, ha egy könyvtárról van szó.

Folyamatok létrehozása

Alapértelmezés szerint egy függvény ugyanabban a folyamatban fut le, amelyikből meghívták. Amikor egy adott függvényt kifejezetten egy új folyamatban szeretnél futtatni, használd a spawn-t:

  • A spawn/1 egy függvényt vár, amelyet közvetlenül végrehajt.

    spawn(fn -> 2 + 2 end)
    # => #PID<0.125.0>
    
  • A spawn/3 egy függvényt vár, amelyet a modul neve, a függvény neve (atomként) és a függvénynek átadandó argumentumok listája alapján hajt végre.

    spawn(String, :split, ["hello there", " "])
    # => #PID<0.113.0>
    
    • Ezt az adathármast gyakran MFA-nak nevezik, azaz Module, Function, Arguments.
  • Egy folyamat azonnal kilép, amint a függvénye befejezte a futását.

  • A Process.alive?/1 segítségével ellenőrizheted, hogy egy folyamat még él-e (fut-e):

    pid = spawn(fn -> 2 + 2 end)
    Process.alive?(pid)
    # => false
    

Üzenetek

A folyamatok nem osztanak meg egymással információt közvetlenül. Az adatok megosztásához üzeneteket küldenek egymásnak. Ez a párhuzamossági minta az úgynevezett Actor model.

  • Üzenetet küldhetsz egy folyamatnak a send/2 segítségével.

    send(pid, :hello)
    
    • Az üzenet a küldésük sorrendjében a címzett postaládájába kerül.
    • A send nem ellenőrzi, hogy megérkezett-e az üzenet, és azt sem, hogy a címzett még él-e.
  • Az üzenet bármilyen típusú lehet.

  • Az aktuális folyamatnak küldött üzenetet a receive/1 segítségével fogadhatod.

    • Az üzenetekre mintaillesztést kell alkalmaznod.
    • A receive addig vár, amíg egy, a megadott minták valamelyikére illeszkedő üzenet meg nem jelenik a folyamat postaládájában.
      • Alapértelmezés szerint korlátlan ideig vár, de egy after blokkal időtúllépést adhatsz neki.
    • Az elolvasott üzenetek eltűnnek a folyamat postaládájából. Az olvasatlan üzenetek korlátlan ideig ott maradnak.
      • Mindig írj egy mindent elkapó _ ágat a receive/1-ben, hogy elkerüld a memóriahiányt a felhalmozódó olvasatlan üzenetek miatt.
    receive do
      {:ping, sender_pid} -> send(sender_pid, :pong)
      _ -> nil
    after
      5000 ->
        {:error, "No message in 5 seconds"}
    end
    

Fogadóciklus

Ha egynél több üzenetet szeretnél fogadni, rekurzívan kell meghívnod a receive/1-et. Gyakori minta egy rekurzív függvény megvalósítása, például loop néven, amely meghívja a receive/1-et, tesz valamit az üzenettel, majd újra meghívja önmagát, hogy további üzenetekre várjon. Ha állapotot kell átvinned az egyik receive/1 hívásból a másikba, azt úgy teheted meg, hogy argumentumot adsz át a loop függvénynek.

def loop(state) do
  receive do
    :increment_by_one ->
      loop(state + 1)

    {:report_state, sender_pid} ->
      send(sender_pid, state)
      loop(state)

    :stop ->
      nil

    _ ->
      loop(state)
  end
end

A gyakorlatban ezt a megközelítést ritkán használják közvetlenül. Az Elixir párhuzamossági absztrakciókat kínál, például az Agent modult vagy a GenServer viselkedést, amelyek mind a fogadóciklusra épülnek. Ugyanakkor kulcsfontosságú megérteni ezeket az alapokat ahhoz, hogy hatékonyan tudd használni az absztrakciókat.

Szerkesztés GitHubon A hivatkozás új ablakban vagy lapon nyílik meg

Tanuld meg a(z) Folyamatok fogalmat

A gyakorlás zárolva

Oldj fel még 4 feladatot, hogy gyakorolhasd a(z) Folyamatok fogalmat