多進程

  使用spawn創建一個新進程,其第一個參數是模塊名、第二個參數是函數名、第三個參數是參數列表。spawn會返回一個進程標識符,通常叫做PID。

defmodule Spawn1 dodef greet doreceive do{sender, msg} ->send sender, { :ok, "Hello #{msg}" }# codeendend
endspawn(SpawnBasic, :greet, [])        #"Hello"

 

進程間發送消息

  使用send發送消息,第一個參數是接收方pid、第二個參數是要發送的消息,通常是原子或者元組。使用receive等待消息,它的用法比較像case。

#以下代碼都在同一個文件中。
defmodule Spawn1 dodef greet do
receive do{sender, msg} ->send sender, { :ok, "Hello #{msg}" }# codeendend endpid = spawn(Spawn1, :greet, []) send pid, {self, "World!"}receive do{:ok, message} ->IO.puts message end

  上述代碼如果想要發送第二條數據,就會導致iex被掛起。因為greet函數在處理完receive后,就退出了。我們永遠等不來receive的相應。我們可以使用 after 指定receive在規定時間內未到達就超時。

receive do{:ok, message} ->IO.puts messageafter 500 ->    #receive在等待500毫秒后,消息未到達就會退出IO.puts "The greeter han gone away"
end

?

  我們可以使用遞歸來處理多條消息。greet:

def greet doreceive do{sender, msg} ->send, sender, { :ok, "Hello, #{msg}" }greetendend
endpid = spawn(Spawn1, :greet, [])
send pid, {self, "World!"}receive do{:ok, message} ->IO.puts message            # "Hello, World!"
endpid = spawn(Spawn1, :greet, [])
send pid, {self, "kermit!"}receive do{:ok, message} ->IO.puts message            # "Hello, Kermit!"after 500 ->IO.puts "The greeter has gone away"
end

?

進程開銷

  很小。

?

  進程調用exit(:boom)會以狀態碼99退出。

?

  關聯兩個進程,使用spawn_link會創建一個進程并和調用者相關聯。

defmodule Link2 do import :timer, only: [ sleep: 1 ]def sad_function dosleep 500exit(:boom)enddef run dospawn_link(Link2, :sad_function, [])receive domsg ->IO.puts "<MESSAGE RECEIVED: #{inspect msg}"after 1000 ->IO.puts "Nothing ... "endend
end

  子進程結束,然后它會結束整個應用,這是關聯進程的默認行為,當其中一個進程非正常退出時會把另一個進程也殺死。

  設置Peocess.flag(:trap_exit, true),可以捕獲進程退出時的消息。

  創建進程時,可以使用spawn_monitor開啟監控(創建 + 監控),也可以使用Process.monitor監控已經存在的進程。當使用Process.monitor時,在調用監控完成前被監控進程死了,就不會受到通知。然而,spawn_link和spawn_monitor操作符合原子性,所以總能捕獲到錯誤。?

?

并行map

  普通map返回列表,該列表是某個收集的每個元素應用于某個函數的結果。并行版本做同樣的事情,但每個元素在獨立的進程里應用于函數。

defmodule Parallel dodef pmap(collection, fun) dome = selfcollection|> Enum.map(fn (elem) ->     #雙重嵌套函數spawn_link fn -> (send me, { self, fun.(elem) } ) end    #返回一組PID,每個PID內都運行了一個計算函數,將自身PID和結果發送給主進程end)|> Enum.map(fn (pid) ->    #在主進程中等待結果receive do {^pid, resuet } -> result endend)end
end

?

斐波拉契數服務器

  編寫一個服務程序來計算斐波拉契數。當計算器準備好接受下一個數字時,它會發送 :ready 消息給調度器,如果仍有任務為完成,調度器會發送 :fib 消息給計算器;否則發送shutdown 給計算器。當計算器接受到 :fib 消息就計算給定的斐波拉契數,并以 :answer 返回結果。如果收到shutdown就退出。

  

defmodule FibSolver do    #計算模塊def fib(scheduler) dosend scheduler, {:ready, self}receive do{ :fib, n, client} ->send client, { :answer, n, fib_calc(n), self}fib(scheduler){ :shutdown } ->exit(:normal)endenddefp fib_calc(0) do0enddefp fib_calc(1) do1enddefp fib_calc(n) dofib_calc(n - 1) + fib_calc(n - 2)end
enddefmodule Scheduler do      #調度模塊def run(num_process, module, func, to_calculate) do(1..num_process)|> Enum.map(fn (_) -> spawn(module, func, [self]) end)|> scheduler_process(to_calculate, [])enddefp scheduler_process(processes, queue, results) doreceive do{:ready, pid} when length(queue) > 0 ->[next | tail] = queuesend pid, {:fib, next, self}scheduler_process(processes, tail, results){:ready, pid} ->send pid, {:shutdown}if length(processes) > 1 doscheduler_process(List.delete(processes, pid), queue, results)elseEnum.sort(results, fn {n1, _}, {n2, _} -> n1 <= n2 end)end{:answer, number, result, _pid}->scheduler_process(processes, queue, [ {number,result} | results])endend
endto_process = [ 37, 37, 37, 37, 37, 37]    #外部調用模塊Enum.each 1..10, fn num_processes ->{time, result} = :timer.tc(Scheduler, :run, [num_processes, FibSolver, :fib, to_process])if num_processes == 1 doIO.puts inspect resultIO.puts "\n #    time (s)"end:io.format "~2B     ~.2f~n", [num_processes, time/1000000.0]
end

?

轉載于:https://www.cnblogs.com/lr1402585172/p/11507966.html

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/384199.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/384199.shtml
英文地址,請注明出處:http://en.pswp.cn/news/384199.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

Linux socket編程(二) 服務器與客戶端的通信

http://www.cnblogs.com/-Lei/archive/2012/09/04/2670964.html上一篇寫了對套接字操作的封裝&#xff0c;這一節使用已封裝好的Socket類實現服務器與客戶端的通信&#xff08;Socket的定義見上篇Socket.h) 服務器端&#xff1a; ServerSocket.h #ifndef SERVERSOCKET_H #defin…

OTP服務器

defmodule Sequence.Server douse GenServerdef handle_call( :next_number, _from, current_number) do{ :reply, current_number, current_number 1}  #reply告訴OTP將第二個元素返回給客戶端end end use的效果將OTP GenServer的行為添加到當前模塊。這樣它就可以處理所有…

洛谷P1040-加分二叉樹-dp+二叉樹

P1040-加分二叉樹 這道題放在深度優先搜索的訓練題中&#xff0c;可是我實在沒有看出來應該怎么搜索。看了題解以后才看出來是一個很簡單的dp(我果然還是太菜了) 看出dp并且算出來最大的分數不是很復雜&#xff0c;關鍵是輸出給定中序遍歷序列的二叉樹的先序遍歷&#xff0c;要…

UNIX網絡編程:I/O復用技術(select、poll、epoll)

http://blog.csdn.net/dandelion_gong/article/details/51673085 Unix下可用的I/O模型一共有五種&#xff1a;阻塞I/O 、非阻塞I/O 、I/O復用 、信號驅動I/O 、異步I/O。此處我們主要介紹第三種I/O符復用。 I/O復用的功能&#xff1a;如果一個或多個I/O條件滿足&#xff08;輸…

解決iex -S mix報錯

執行iex -S mix命令的時候會遇到如下錯誤&#xff1a; 執行 mix deps.get 然后就可以運行 iex -S mix了 其中&#xff0c;有可能會出現 按照其網站下載相應文件&#xff0c;復制到項目根目錄下&#xff0c;然后執行命令&#xff08;mix local.rebar rebar ./rebar&#xff09;即…

貪心算法——選擇不相交區間問題

題目描述&#xff1a;設有n個活動的集合&#xff0c;其中每個活動都要求使用同一個資源&#xff0c;而在同一時間內只有一個活動能夠使用這一資源&#xff0c;每個活動i都有一個要求使用該資源的起始時間si和一個結束時間fi(si<fi)&#xff0c;如果選擇了活動i&#xff0c;則…

Anker—工作學習筆記

http://www.cnblogs.com/Anker/archive/2013/08/17/3263780.html 1、基本知識 epoll是在2.6內核中提出的&#xff0c;是之前的select和poll的增強版本。相對于select和poll來說&#xff0c;epoll更加靈活&#xff0c;沒有描述符限制。epoll使用一個文件描述符管理多個描述符&am…

Supervisor監控

可參考&#xff1a;https://www.cnblogs.com/wang_yb/archive/2016/06/08/5564459.html &#xff1a;https://segmentfault.com/a/1190000007379204 轉載于:https://www.cnblogs.com/lr1402585172/p/11551488.html

深度搜索剪枝——數的劃分

【題目描述】將整數n分成k份&#xff0c;且每份不能為空&#xff0c;問有多少種分法&#xff1f; 【輸入格式】兩個整數n,m(6<n<200,2<m<6) 【輸出格式】輸出不同的分法數 【樣例輸入】7 3 【樣例輸出】4 對于這種搜索題&#xff0c;關鍵就在于剪枝&#xff1a;確定…

Linux網絡編程——tcp并發服務器(I/O復用之select

http://blog.csdn.net/lianghe_work/article/details/46519633 與多線程、多進程相比&#xff0c;I/O復用最大的優勢是系統開銷小&#xff0c;系統不需要建立新的進程或者線程&#xff0c;也不必維護這些線程和進程。 代碼示例&#xff1a; [csharp] view plaincopy #include &…

ets

:ets.new(table_name, pattern) 第一個參數是表名&#xff0c;第二個參數是表的設置選項。 :set  一個key&#xff0c;一個數據&#xff0c;無序 :ordered_set  一個key&#xff0c;一個數據&#xff0c;有序&#xff1b; 1 1.0 :bag  一個key&#xff0c;多個數據&…

貪心算法-區間選點問題-種樹

【題目描述】一條街道的一邊有幾座房子。因為環保原因居民想要在路邊種些樹&#xff0c;路邊的地區被分割成n塊&#xff0c;并被編號為1~n。每塊大小為一個單位尺寸且最多可總一棵樹。每個居民想在門前種些樹并制定了三個數b,e,t&#xff0c;這三個數代表居民想在b和e之間最少種…

ets注意事項

當表類型為 :set 時&#xff0c;使用 :ets.first 和 :ets.last 會獲取到同一個 key。將表類型換為 :oedered_set 就可以避免這種情況 轉載于:https://www.cnblogs.com/lr1402585172/p/11599219.html

CodeForces - 1141CPolycarp Restores Permutation搜索+剪枝

Polycarp Restores Permutation 【題意分析】題意大概是給定一個串&#xff0c;包含從1到n所有的數字。但是給定的是相鄰數字的差&#xff0c;需要復原這個串。 大概分析以后發現給定的是一個差分數組&#xff0c;所以只需要枚舉第一個元素就可以確定所有元素的值。 問題是如何…

CodeForces - 1141ESuperhero Battle簡單模擬

Superhero Battle 這道題卡了我一個多小時&#xff0c;最后也沒有做出來&#xff0c;成功稱為吊車尾。。。 思路什么的都沒有問題&#xff0c;主要是&#xff0c;爆long long了&#xff0c;這個太可怕了&#xff0c;就因為一個中間變量忘記開longlong導致一直一直wa&#xff0c…

Linux下的I/O復用與epoll詳解

http://www.cnblogs.com/lojunren/p/3856290.html 前言 I/O多路復用有很多種實現。在linux上&#xff0c;2.4內核前主要是select和poll&#xff0c;自Linux 2.6內核正式引入epoll以來&#xff0c;epoll已經成為了目前實現高性能網絡服務器的必備技術。盡管他們的使用方法不盡相…

校門外的樹——樹狀數組+區間修改

校門外的樹 【題目分析】題目描述的是一種區間修改&#xff0c;看起來好像要用線段樹。但是對于這種區間內部沒有差別并且查詢的是區間內的類別的問題&#xff0c;是可以轉化為樹狀數組進行的。畢竟樹狀數組更加簡單。 我們的關注點應該放在區間的端點處&#xff0c;然后通過統…

數據結構--順序棧和鏈式棧

http://www.cnblogs.com/jingliming/p/4602458.html 棧是一種限定只在表尾進行插入或刪除操作,棧也是線性表表頭稱為棧的底部,表尾稱為棧的頂部,表為空稱為空棧&#xff0c;棧又稱為后進先出的線性表,棧也有兩種表示:順序棧與鏈式棧順序棧是利用一組地址連續的存儲單元&#xf…

CodeForces - 1144F搜索+簡單圖論

【題目鏈接】Graph Without Long Directed Paths 【題目分析】題目想要講一個無向圖變成一個最長路徑不超過1的有向圖。假如某個邊是從u到v的&#xff0c;那么所有和v相連的都必須是指向v的&#xff0c;所有和u相連的都必須是從u開始的。相當于涂色&#xff0c;相連的節點應該涂…

數據結構--雙鏈表的創建和操作

http://www.cnblogs.com/jingliming/p/4602144.html#0-tsina-1-42616-397232819ff9a47a7b7e80a40613cfe1 一、雙向鏈表的定義 雙向鏈表也叫雙鏈表&#xff0c;是鏈表的一種&#xff0c;它的每個數據結點中都有兩個指針&#xff0c;分別指向直接后繼和直接前驅。所以&#xff0c…