Erlang并发处理实战案例

琉璃若梦 2021-10-07 ⋅ 13 阅读

Erlang是一种函数式编程语言,以并发处理闻名。它提供了许多强大的工具和库,帮助开发者处理并发任务。本文将介绍一些Erlang中的并发处理实战案例,展示其强大的并发能力。

1. 并发服务器

在Erlang中,我们可以轻松地编写并发服务器。以下是一个简单的示例,演示了如何创建一个支持并发连接的TCP服务器:

-module(server).
-export([start/1]).

start(Port) ->
    {ok, Listen} = gen_tcp:listen(Port, [{active, false}, {reuseaddr, true}]),
    loop(Listen).

loop(Listen) ->
    {ok, Socket} = gen_tcp:accept(Listen),
    spawn(fun() -> handle(Socket) end),
    loop(Listen).

handle(Socket) ->
    case gen_tcp:recv(Socket, 0) of
        {ok, Request} ->
            Response = process_request(Request),
            gen_tcp:send(Socket, Response),
            handle(Socket);
        {error, closed} -> ok
    end.

process_request(Request) ->
    % 处理请求的代码

上述代码创建了一个TCP服务器,侦听特定的端口。每当有新的连接请求到来时,将会创建一个新的进程来处理连接。这样,服务器就可以并发处理多个连接,而不会阻塞其他连接。

2. 并发任务执行

在Erlang中,我们可以使用spawn/1函数来创建新的进程执行并发任务。以下是一个示例,展示了如何同时执行多个并发任务:

-module(concurrent_tasks).
-export([start/1]).

start(NumTasks) ->
    TaskRefs = [spawn(fun() -> process_task(TaskNumber) end) || TaskNumber <- lists:seq(1, NumTasks)],
    wait_for_tasks(TaskRefs).

process_task(TaskNumber) ->
    % 执行任务的代码

wait_for_tasks([]) -> ok;
wait_for_tasks(TaskRefs) ->
    receive
        {TaskRef, Result} ->
            io:format("Task ~p completed with result ~p~n", [TaskRef, Result]),
            wait_for_tasks(lists:delete(TaskRef, TaskRefs))
    end.

上述示例代码使用了spawn/1函数来创建指定数量的并发任务。每个任务将会在一个新的进程中执行。wait_for_tasks/1函数等待所有任务执行完成并输出结果。

3. 并发消息传递

Erlang以消息传递作为主要的并发通信机制。以下是一个示例,展示了如何在不同进程间进行消息传递:

-module(message_passing).
-export([start/1]).

start(NumWorkers) ->
    ManagerPid = spawn(fun() -> manager(NumWorkers) end),
    ManagerPid ! {self(), start},
    receive
        {manager_started, ManagerPid} ->
            io:format("Manager started with PID ~p~n", [ManagerPid])
    end.

manager(NumWorkers) ->
    io:format("Manager started~n"),
    Workers = [spawn_link(fun() -> worker(ManagerPid) end) || _ <- lists:seq(1, NumWorkers)],
    io:format("Spawned ~p workers~n", [NumWorkers]),
    loop(Workers, []).

loop(Workers, CompletedTasks) ->
    receive
        {From, start} ->
            TaskPid = hd(Workers),
            NewWorkers = tl(Workers),
            TaskPid ! {self(), task},
            loop(NewWorkers, [{From, TaskPid} | CompletedTasks]);
        {worker_completed, TaskPid, Result} ->
            case lists:keyfind(TaskPid, 2, CompletedTasks) of
                {From, _} ->
                    From ! {task_completed, Result},
                    loop(Workers ++ [spawn_link(fun() -> worker(self()) end)], lists:keydelete(TaskPid, 2, CompletedTasks))
            end
    end.

worker(ManagerPid) ->
    io:format("Worker started with PID ~p~n", [self()]),
    loop(ManagerPid).

loop(ManagerPid) ->
    receive
        {From, task} ->
            % 执行任务的代码
            Result = do_task(),
            ManagerPid ! {worker_completed, self(), Result},
            loop(ManagerPid)
    end.

do_task() ->
    % 执行任务的代码

上述示例代码创建了一个任务管理器进程和多个工作进程。任务管理器将会等待外部命令,然后将任务分发给空闲的工作进程。工作进程完成任务后,将结果发送回任务管理器。任务管理器将结果发送给任务的发送方。

总结:Erlang提供了许多丰富的机制和工具,用于处理并发任务。无论是创建并发服务器、执行并发任务还是进行并发消息传递,Erlang都是一个非常强大的选择。希望本文的案例能够帮助您更好地理解Erlang的并发处理能力。


全部评论: 0

    我有话说: