Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

This article is a Private article. Only a writer and users who know the URL can access it.
Please change open range to public in publish setting if you want to share this article with other users.

Elixirの並行処理入門 - 簡単に使えるActorモデルとTaskを理解しよう

Posted at

Elixirの並行処理入門 - 簡単に使えるActorモデルとTaskを理解しよう

はじめに

Elixirは、並行処理や分散システムの構築を容易にするために設計されたプログラミング言語です。Elixirの背後にあるErlang VM(BEAM)は、数十年にわたって高可用性とスケーラビリティを提供してきました。この特性を活かし、Elixirを使って並行処理を実現する方法を学ぶことは、現代のアプリケーション開発において非常に重要です。

本記事では、Elixirの並行処理の基本として、ActorモデルとTaskを使用した具体的なコード例を交えながら解説します。初心者の方でも理解できるように丁寧に説明しますので、ぜひ最後までお付き合いください。

Elixirの並行処理とは?

Elixirの並行処理は、主に以下の2つの概念に基づいています。

  1. Actorモデル: プロセス(Actor)がメッセージを介して相互作用し、状態を持たずに独立して動作します。
  2. Task: 簡易的な非同期処理を実行するための機能で、バックグラウンドでコードを実行できます。

これらの機能を利用することで、Elixirはシンプルで直感的な並行処理を提供します。

Actorモデルの基本

プロセスの生成

Elixirでは、プロセスを簡単に生成できます。spawn関数を使用して新しいプロセスを作成し、並行して実行させることができます。以下のコードは、プロセスを生成してメッセージを受信する例です。

defmodule MyActor do
  def start do
    # 新しいプロセスを生成し、メッセージを受信する
    spawn(fn -> loop() end)
  end

  defp loop do
    receive do
      {:hello, sender} ->
        IO.puts("Hello from process #{inspect sender}")
        loop() # 再帰的にループを続ける

      _ ->
        IO.puts("Unknown message")
        loop() # 他のメッセージも受け取る
    end
  end
end

# プロセスを開始
pid = MyActor.start()
send(pid, {:hello, self()}) # メッセージを送信

コード解説

  1. spawn(fn -> loop() end)で新しいプロセスを生成します。
  2. loop関数は、receiveブロック内でメッセージを待ち受け、受け取ったメッセージに応じて処理を行います。
  3. send(pid, {:hello, self()})で、生成したプロセスにメッセージを送信します。

ハマりやすいポイント

  • 無限ループ: loop関数内で再帰的に呼び出すことで、メッセージを常に受け取る状態を維持しますが、適切に終了条件を設定しないと無限ループになります。
  • メッセージの整合性: 受信するメッセージの形式を統一しないと、Unknown messageが頻発することがあります。

Taskを使った非同期処理

ElixirのTaskモジュールを利用すると、簡単に非同期処理を実行できます。以下に例を示します。

defmodule MyTask do
  def run do
    # 非同期でタスクを実行
    task = Task.async(fn -> perform_heavy_computation() end)

    # 他の処理をここで行う
    IO.puts("Doing something else...")

    # タスクの結果を取得
    result = Task.await(task)
    IO.puts("Task result: #{result}")
  end

  defp perform_heavy_computation do
    # 重い計算処理の模擬
    :timer.sleep(2000) # 2秒待機
    42 # 結果を返す
  end
end

# タスクを実行
MyTask.run()

コード解説

  1. Task.async/1で非同期にタスクを実行します。ここでは、重い計算処理を模擬しています。
  2. Task.await/1で、非同期処理の結果を待機します。この間に他の処理を行うことができます。

ハマりやすいポイント

  • タイムアウト: Task.await/1はデフォルトで無限に待機しますが、時間を指定することも可能です。指定しないと、タスクが完了しない場合に永遠に待つことになります。次のようにしてタイムアウトを設定できます。
result = Task.await(task, 5000) # 5秒待機

まとめ

Elixirの並行処理は非常に強力で、ActorモデルとTaskを使用することで簡単に実現できます。プロセス間でメッセージをやりとりすることで、スケーラブルで高可用性なアプリケーションを構築可能です。

本記事では、Elixirの並行処理の基本を学び、実用的なコード例を通じて理解を深めました。これを基に、さらに複雑な並行処理や分散システムの構築に挑戦してみてください。

ぜひ、Elixirを使った並行処理の魅力を楽しんでください!

0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?