{"id":63878,"date":"2017-02-15T22:00:18","date_gmt":"2017-02-15T20:00:18","guid":{"rendered":"https:\/\/www.javacodegeeks.com\/?p=63878"},"modified":"2017-02-15T14:37:44","modified_gmt":"2017-02-15T12:37:44","slug":"concurrency-in-elixir","status":"publish","type":"post","link":"https:\/\/www.javacodegeeks.com\/2017\/02\/concurrency-in-elixir.html","title":{"rendered":"Concurrency in Elixir"},"content":{"rendered":"<p>Erlang has been around for over 30 years and was built well before multi-core CPUs existed. Yet it\u2019s a language that couldn\u2019t be more relevant today! The underlying architecture of the language lends itself perfectly to the modern CPUs that are on every computer and mobile device.<\/p>\n<p>The computer I\u2019m writing this article on has a 2.2 GHz Intel Core i7 CPU, but more importantly it comes with eight cores. Simply put, it can perform eight tasks at once.<\/p>\n<p>The ability to take advantage of these cores exists in many languages but often feels out of place or fraught with traps and challenges. If you\u2019ve ever had to worry about a <a href=\"https:\/\/en.wikipedia.org\/wiki\/Mutual_exclusion\">mutex<\/a>, <a href=\"http:\/\/manishearth.github.io\/blog\/2015\/05\/17\/the-problem-with-shared-mutability\/\">shared mutable state<\/a>, and code being <a href=\"https:\/\/en.wikipedia.org\/wiki\/Thread_safety\">thread safe<\/a>, you know that there are at least several pitfalls to be wary of.<\/p>\n<p>In Erlang, and therefor Elixir which leverages the Erlang VM (BEAM), it makes writing and reasoning about concurrent code feel effortless. While Ruby has some <a href=\"https:\/\/github.com\/ruby-concurrency\/concurrent-ruby\">great libraries<\/a> for helping write concurrent code, with Elixir it\u2019s built-in and a first-class citizen.<\/p>\n<p>That isn\u2019t to say that writing highly concurrent or distributed systems is easy. Far from it! But with Elixir, the language is on your side.<\/p>\n<h2>Processes, PIDs, and Mailboxes<\/h2>\n<p>Before we look at how to go about writing concurrent code in Elixir, it\u2019s a good idea to understand the terms that we\u2019ll be using and the model of concurrency that Elixir employs.<\/p>\n<h3>Actor Model<\/h3>\n<p>Concurrency in Elixir (and Erlang) is based upon the <a href=\"https:\/\/en.wikipedia.org\/wiki\/Actor_model\">Actor Model<\/a>. Actors are single threaded processes which can send and receive messages amongst themselves. The Erlang VM manages their creation, execution, and their communication. Their memory is completely isolated, which makes having to worry about \u201cshared state\u201d a non-issue.<\/p>\n<p><a href=\"http:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2017\/02\/actors.png\"><img decoding=\"async\" class=\"aligncenter wp-image-63888\" src=\"http:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2017\/02\/actors.png\" width=\"860\" height=\"999\" srcset=\"https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2017\/02\/actors.png 1018w, https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2017\/02\/actors-258x300.png 258w, https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2017\/02\/actors-768x892.png 768w, https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2017\/02\/actors-882x1024.png 882w\" sizes=\"(max-width: 860px) 100vw, 860px\" \/><\/a><\/p>\n<ul>\n<li><strong>Process<\/strong>: Similar to an OS level thread, but much more lightweight. This is essentially the unit of concurrency in Elixir. The processes are managed by BEAM (the Erlang runtime), which handles spreading the work out over all the cores of the CPU or even across other BEAM nodes on the network. A system can have millions of these processes at a time, and you shouldn\u2019t be afraid to take liberal advantage of them.<\/li>\n<li><strong>Process ID (PID)<\/strong>: This is a reference to a specific process. Much like an IP address on the internet, a PID is how you tell Elixir which process you want to send a message to.<\/li>\n<li><strong>Mailbox<\/strong>: For processes to communicate with each other, messages are sent back and forth. When a message is sent to a process, it arrives to that process\u2019 mailbox. It is up to that process to receive the messages sitting in its mailbox.<\/li>\n<\/ul>\n<p>So to bring it all together, a process in Elixir is the actor. It can communicate with another actor by sending a message to a specific PID. The recipient can receive a message by checking its mailbox for new messages.<\/p>\n<h2>Writing Concurrent Code<\/h2>\n<p>In this section, we\u2019ll look at how the Actor Model for concurrency is actually used within Elixir.<\/p>\n<h3>Creating processes<\/h3>\n<p>Creating a new process is done with the <code>spawn<\/code> or <code>spawn_link<\/code> functions. This function accepts an anonymous function which will be invoked in a separate process. In response, we are given a process identifier, often referred to as a PID. This is important if we want to communicate with this process going forward or ask the kernel for information about the process.<\/p>\n<pre class=\"brush:java\">pid = spawn(fn -&gt; :timer.sleep 15000 end)\r\n#PID&lt;0.89.0&gt;<\/pre>\n<p>Everything in Elixir runs within a process. You can find out the PID of your current process by calling the <code>self()<\/code> function. So even when you are in the <code>iex<\/code> shell, by calling <code>self()<\/code> you can see the PID for that iex session, something like <code>#PID&lt;0.80.0&gt;<\/code>.<\/p>\n<p>We can use this PID to ask Elixir for information about the process. This is done using the <code>Process.info(pid)<\/code> function.<\/p>\n<pre class=\"brush:java\">Process.info(pid)\r\n\r\n[current_function: {:timer, :sleep, 1}, initial_call: {:erlang, :apply, 2},\r\n status: :waiting, message_queue_len: 0, messages: [], links: [],\r\n dictionary: [], trap_exit: false, error_handler: :error_handler,\r\n priority: :normal, group_leader: #PID&lt;0.50.0&gt;, total_heap_size: 233,\r\n heap_size: 233, stack_size: 2, reductions: 43,\r\n garbage_collection: [max_heap_size: %{error_logger: true, kill: true, size: 0},\r\n  min_bin_vheap_size: 46422, min_heap_size: 233, fullsweep_after: 65535,\r\n  minor_gcs: 0], suspending: []]<\/pre>\n<p>It\u2019s interesting what you can find here! For example, in <code>iex<\/code> if you ask for the info about itself <code>Process.info(self())<\/code>, you\u2019ll see the history of the commands you\u2019ve typed:<div style=\"display:inline-block; margin: 15px 0;\"> <div id=\"adngin-JavaCodeGeeks_incontent_video-0\" style=\"display:inline-block;\"><\/div> <\/div><\/p>\n<pre class=\"brush:java\">iex(1)&gt; 5 + 5\r\niex(2)&gt; IO.puts \"Hello!\"\r\niex(3)&gt; pid = spawn(fn -&gt; :timer.sleep 15000 end)\r\niex(4)&gt; Process.info(self())[:dictionary][:iex_history]\r\n\r\n%IEx.History.State{queue: {[\r\n  {3, 'pid = spawn(fn -&gt; :timer.sleep 15000 end)\\n', #PID&lt;0.84.0&gt;},\r\n  {2, 'IO.puts \"Hello!\"\\n', :ok}],\r\n  [{1, '5 + 5\\n', 10}]},\r\n size: 3, start: 1}<\/pre>\n<h3>Sending messages<\/h3>\n<p>Messages can be sent to a process using the <code>send<\/code> function. You provide it with the PID of the process you wish to send a message to along with the data being sent. The message is sent to the receiving processes\u2019 mailbox.<\/p>\n<p>Sending is only half the battle though. If the recipient isn\u2019t prepared to receive the message, it will fall on deaf ears. A process can receive messages by using the <code>receive<\/code> construct, which pattern matches on the messages being received.<\/p>\n<p>In the example below, we spawn a new process which waits to receive a message. Once it has received a message in its mailbox, we\u2019ll simply output it to the screen.<\/p>\n<pre class=\"brush:java\">pid = spawn(fn -&gt;\r\n  IO.puts \"Waiting for messages\"\r\n  receive do\r\n    msg -&gt; IO.puts \"Received #{inspect msg}\"\r\n  end\r\nend)\r\n\r\nsend(pid, \"Hello Process!\")<\/pre>\n<h3>Keeping our process alive<\/h3>\n<p>A process exits when it no longer has any code to execute. In the example above, the process will stay alive until it has received its first message, then exit. So the question then arises: How do we get a long running process?<\/p>\n<p>We can do this by utilizing a <code>loop<\/code> function that calls itself recursively. This loop will simply receive a message and then call itself to wait for the next one.<\/p>\n<pre class=\"brush:java\">defmodule MyLogger do\r\n  def start do\r\n    IO.puts \"#{__MODULE__} at your service\"\r\n    loop()\r\n  end\r\n\r\n  def loop do\r\n    receive do\r\n      msg -&gt; IO.puts msg\r\n    end\r\n    loop()\r\n  end\r\nend\r\n\r\n# This time we will spawn a new processes based on the MyLogger module's method `start`.\r\npid = spawn(MyLogger, :start, [])\r\n\r\nsend(pid, \"First message\")\r\nsend(pid, \"Another message\")<\/pre>\n<h3>Maintaining state<\/h3>\n<p>Our current process doesn\u2019t track any state. It simply executes its code without maintaining any extra state or information.<\/p>\n<p>What if we wanted our logger to keep track of some stats, like the number of messages it has logged? Notice the call <code>spawn(MyLogger, :start, [])<\/code>; the last parameter, which is an empty list, is actually a list of args that can be passed to the process. This acts as the \u201cinitial state\u201d or what is passed to the entry point function. Our state will simply be a number that tracks the number of messages we\u2019ve logged.<\/p>\n<p>Now, when the <code>init<\/code> function is called, it will be passed the number <code>0<\/code>. It\u2019s up to us to keep track of this number as we do our work, always passing the updated state to the next loop of our process.<\/p>\n<p>Another thing we\u2019ve done is added an additional action our logger can perform. It can now log messages and also print out the stats. To do this, we\u2019ll send our messages as a <code>tuple<\/code> where the first value is an <code>atom<\/code> that represents the command we want our process to perform. Pattern matching in the <code>receive<\/code> construct allows us to differ one message\u2019s intent from another.<\/p>\n<pre class=\"brush:java\">defmodule MyLogger do\r\n  def start_link do\r\n    # __MODULE__ refers to the current module\r\n    spawn(__MODULE__, :init, [0])\r\n  end\r\n\r\n  def init(count) do\r\n    # Here we could initialize other values if we wanted to\r\n    loop(count)\r\n  end\r\n\r\n  def loop(count) do\r\n    new_count = receive do\r\n      {:log, msg} -&gt;\r\n        IO.puts msg\r\n        count + 1\r\n      {:stats} -&gt;\r\n        IO.puts \"I've logged #{count} messages\"\r\n        count\r\n    end\r\n    loop(new_count)\r\n  end\r\nend\r\n\r\npid = MyLogger.start_link\r\nsend(pid, {:log, \"First message\"})\r\nsend(pid, {:log, \"Another message\"})\r\nsend(pid, {:stats})<\/pre>\n<h3>Refactoring into a client and server<\/h3>\n<p>We can refactor our module a little bit to make it more user friendly. Instead of directly using the <code>send<\/code> function, we can hide the details behind a client module. Its job will be to send messages to the process running the server module and optionally wait for a response for synchronous calls.<\/p>\n<pre class=\"brush:java\">defmodule MyLogger.Client do\r\n  def start_link do\r\n    spawn(MyLogger.Server, :init, [0])\r\n  end\r\n\r\n  def log(pid, msg) do\r\n    send(pid, {:log, msg})\r\n  end\r\n\r\n  def print_stats(pid) do\r\n    send(pid, {:print_stats})\r\n  end\r\n\r\n  def return_stats(pid) do\r\n    send(pid, {:return_stats, self()})\r\n    receive do\r\n      {:stats, count} -&gt; count\r\n    end\r\n  end\r\nend<\/pre>\n<p>Our server module is quite simple. It consists of an <code>init<\/code> function which doesn\u2019t do much in this case other than start the <code>loop<\/code> function looping. The <code>loop<\/code> function is in charge of receiving messages from the mailbox, performing the requested task and then looping again with the updated state.<\/p>\n<pre class=\"brush:java\">defmodule MyLogger.Server do\r\n  def init(count \\\\ 0) do\r\n    loop(count)\r\n  end\r\n\r\n  def loop(count) do\r\n    new_count = receive do\r\n      {:log, msg} -&gt;\r\n        IO.puts msg\r\n        count + 1\r\n      {:print_stats} -&gt;\r\n        IO.puts \"I've logged #{count} messages\"\r\n        count\r\n      {:return_stats, caller} -&gt;\r\n        send(caller, {:stats, count})\r\n        count\r\n    end\r\n    loop(new_count)\r\n  end\r\nend<\/pre>\n<p>If we are to use the code below, we don\u2019t really need to know how the server is implemented. We interact directly with the client, and it in turn sends messages to the server. I\u2019ve aliased the module just to avoid typing <code>MyLogger.Client<\/code> various times.<\/p>\n<pre class=\"brush:java\">alias MyLogger.Client, as: Logger\r\n\r\npid = Logger.start_link\r\nLogger.log(pid, \"First message\")\r\nLogger.log(pid, \"Another message\")\r\nLogger.print_stats(pid)\r\nstats = Logger.return_stats(pid)<\/pre>\n<h3>Refactoring the server<\/h3>\n<p>Notice that all of the messages being received by the server are being pattern matched in order to determine how to handle them? We can do better than having a single large function by creating a series of \u201chandler\u201d functions that pattern match on the data being received.<\/p>\n<p>Not only does this clean up our code, it also makes it much easier to test. We can simply call the individual <code>handle_receive<\/code> functions with the correct arguments to test that they are working correctly.<\/p>\n<pre class=\"brush:java\">defmodule MyLogger.Server do\r\n  def init(count \\\\ 0) do\r\n    loop(count)\r\n  end\r\n\r\n  def loop(count) do\r\n    new_count = receive do\r\n      message -&gt; handle_receive(message, count)\r\n    end\r\n    loop(new_count)\r\n  end\r\n\r\n  def handle_receive({:log, msg}, count) do\r\n    IO.puts msg\r\n    count + 1\r\n  end\r\n\r\n  def handle_receive({:print_stats}, count) do\r\n    IO.puts \"I've logged #{count} messages\"\r\n    count\r\n  end\r\n\r\n  def handle_receive({:return_stats, caller}, count) do\r\n    send(caller, {:stats, count})\r\n    count\r\n  end\r\n\r\n  def handle_receive(other, count) do\r\n    IO.puts \"Unhandled message of #{inspect other} received by logger\"\r\n    count\r\n  end\r\nend<\/pre>\n<h3>Parallel map<\/h3>\n<p>For a final example, let\u2019s take a look at performing a parallel map.<\/p>\n<p>What we\u2019ll be doing is mapping a list of URLs to their returned HTTP status code. If we were to do this without any concurrency, our speed would be the sum of the speed of checking each URL. If we had five and each took oe second, it would take approximately five seconds to finish checking all the URLs. If we could check them in parallel though, the amount of time would be about one second, the time of the slowest URL since they are happening all at once.<\/p>\n<p>Our test implementation looks like this:<\/p>\n<pre class=\"brush:java\">defmodule StatusesTest do\r\n  use ExUnit.Case\r\n\r\n  test \"parallel status map\" do\r\n    urls = [\r\n      url1 = \"http:\/\/www.fakeresponse.com\/api\/?sleep=2\",\r\n      url2 = \"http:\/\/www.fakeresponse.com\/api\/?sleep=1\",\r\n      url3 = \"http:\/\/www.fakeresponse.com\/api\/?status=500\",\r\n      url4 = \"https:\/\/www.leighhalliday.com\",\r\n      url5 = \"https:\/\/www.reddit.com\"\r\n    ]\r\n    assert Statuses.map(urls) == [\r\n      {url1, 200},\r\n      {url2, 200},\r\n      {url3, 500},\r\n      {url4, 200},\r\n      {url5, 200}\r\n    ]\r\n  end\r\nend<\/pre>\n<p>Now for the implementation of the actual code. I\u2019ve added comments to make it clear what each step is doing.<\/p>\n<pre class=\"brush:java\">defmodule Statuses do\r\n  def map(urls) do\r\n    # Put self into variable to send to spawned process\r\n    caller = self()\r\n    urls\r\n      # Map the URLs to a spawns process. Remember a `pid` is returned.\r\n      |&gt; Enum.map(&amp;(spawn(fn -&gt; process(&amp;1, caller) end)))\r\n      # Map the returned pids\r\n      |&gt; Enum.map(fn pid -&gt;\r\n          # Receive the response from this pid\r\n          receive do\r\n            {^pid, url, status} -&gt; {url, status}\r\n          end\r\n        end)\r\n  end\r\n\r\n  def process(url, caller) do\r\n    status =\r\n      case HTTPoison.get(url) do\r\n        {:ok, %HTTPoison.Response{status_code: status_code}} -&gt;\r\n          status_code\r\n        {:error, %HTTPoison.Error{reason: reason}} -&gt;\r\n          {:error, reason}\r\n      end\r\n    # Send message back to caller with result\r\n    send(caller, {self(), url, status})\r\n  end\r\nend<\/pre>\n<p>When we ran the code, it took 2.2 seconds. This makes sense because one of the URLs is a faker URL service that we told to delay the response by two seconds\u2026so it took approximately the time of the slowest URL.<\/p>\n<h2>Where to go from here?<\/h2>\n<p>In this article, we covered the basics of spawning a new process, sending that process a message, maintaining state in the process via recursive looping, and receiving messages from other processes. This is a good start, but there is a lot more!<\/p>\n<p>Elixir comes with some very cool modules to help us remove some of the boilerplate involved in what we did today. <code>Agent<\/code> is a module for maintaining state in a process. <code>Task<\/code> is a module for running code concurrently and optionally receiving its response. <code>GenServer<\/code> handles both state and concurrent tasks in a long standing process. I plan on covering these topics in a second article in this series.<\/p>\n<p>Lastly there is the whole topic of linking, monitoring, and responding to errors which may occur in a process. Elixir comes with a <a href=\"https:\/\/hexdocs.pm\/elixir\/Supervisor.html\">Supervisor<\/a> module for this and is all part of building a dependable fault-tolerant system.<\/p>\n<div class=\"attribution\">\n<table>\n<tbody>\n<tr>\n<td><span class=\"reference\">Reference: <\/span><\/td>\n<td><a href=\"https:\/\/blog.codeship.com\/concurrency-in-elixir\/\">Concurrency in Elixir<\/a> from our <a href=\"http:\/\/www.javacodegeeks.com\/join-us\/jcg\/\">JCG partner<\/a> Leigh Halliday at the <a href=\"http:\/\/blog.codeship.com\/\">Codeship Blog<\/a> blog.<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<\/div>\n","protected":false},"excerpt":{"rendered":"<p>Erlang has been around for over 30 years and was built well before multi-core CPUs existed. Yet it\u2019s a language that couldn\u2019t be more relevant today! The underlying architecture of the language lends itself perfectly to the modern CPUs that are on every computer and mobile device. The computer I\u2019m writing this article on has &hellip;<\/p>\n","protected":false},"author":1300,"featured_media":113,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[15],"tags":[1303,181],"class_list":["post-63878","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-software-development","tag-elixir","tag-erlang"],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v27.5 - https:\/\/yoast.com\/product\/yoast-seo-wordpress\/ -->\n<title>Concurrency in Elixir - Java Code Geeks<\/title>\n<meta name=\"description\" content=\"Erlang has been around for over 30 years and was built well before multi-core CPUs existed. Yet it\u2019s a language that couldn\u2019t be more relevant today! The\" \/>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/www.javacodegeeks.com\/2017\/02\/concurrency-in-elixir.html\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Concurrency in Elixir - Java Code Geeks\" \/>\n<meta property=\"og:description\" content=\"Erlang has been around for over 30 years and was built well before multi-core CPUs existed. Yet it\u2019s a language that couldn\u2019t be more relevant today! The\" \/>\n<meta property=\"og:url\" content=\"https:\/\/www.javacodegeeks.com\/2017\/02\/concurrency-in-elixir.html\" \/>\n<meta property=\"og:site_name\" content=\"Java Code Geeks\" \/>\n<meta property=\"article:publisher\" content=\"https:\/\/www.facebook.com\/javacodegeeks\" \/>\n<meta property=\"article:published_time\" content=\"2017-02-15T20:00:18+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2012\/10\/erlang-logo.jpg\" \/>\n\t<meta property=\"og:image:width\" content=\"150\" \/>\n\t<meta property=\"og:image:height\" content=\"150\" \/>\n\t<meta property=\"og:image:type\" content=\"image\/jpeg\" \/>\n<meta name=\"author\" content=\"Leigh Halliday\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:creator\" content=\"@javacodegeeks\" \/>\n<meta name=\"twitter:site\" content=\"@javacodegeeks\" \/>\n<meta name=\"twitter:label1\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data1\" content=\"Leigh Halliday\" \/>\n\t<meta name=\"twitter:label2\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data2\" content=\"12 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\\\/\\\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/2017\\\/02\\\/concurrency-in-elixir.html#article\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/2017\\\/02\\\/concurrency-in-elixir.html\"},\"author\":{\"name\":\"Leigh Halliday\",\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/#\\\/schema\\\/person\\\/d97c5de664686c98502d9f7e91603b44\"},\"headline\":\"Concurrency in Elixir\",\"datePublished\":\"2017-02-15T20:00:18+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/2017\\\/02\\\/concurrency-in-elixir.html\"},\"wordCount\":1630,\"commentCount\":0,\"publisher\":{\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/#organization\"},\"image\":{\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/2017\\\/02\\\/concurrency-in-elixir.html#primaryimage\"},\"thumbnailUrl\":\"https:\\\/\\\/www.javacodegeeks.com\\\/wp-content\\\/uploads\\\/2012\\\/10\\\/erlang-logo.jpg\",\"keywords\":[\"Elixir\",\"Erlang\"],\"articleSection\":[\"Software Development\"],\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"CommentAction\",\"name\":\"Comment\",\"target\":[\"https:\\\/\\\/www.javacodegeeks.com\\\/2017\\\/02\\\/concurrency-in-elixir.html#respond\"]}]},{\"@type\":\"WebPage\",\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/2017\\\/02\\\/concurrency-in-elixir.html\",\"url\":\"https:\\\/\\\/www.javacodegeeks.com\\\/2017\\\/02\\\/concurrency-in-elixir.html\",\"name\":\"Concurrency in Elixir - Java Code Geeks\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/2017\\\/02\\\/concurrency-in-elixir.html#primaryimage\"},\"image\":{\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/2017\\\/02\\\/concurrency-in-elixir.html#primaryimage\"},\"thumbnailUrl\":\"https:\\\/\\\/www.javacodegeeks.com\\\/wp-content\\\/uploads\\\/2012\\\/10\\\/erlang-logo.jpg\",\"datePublished\":\"2017-02-15T20:00:18+00:00\",\"description\":\"Erlang has been around for over 30 years and was built well before multi-core CPUs existed. Yet it\u2019s a language that couldn\u2019t be more relevant today! The\",\"breadcrumb\":{\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/2017\\\/02\\\/concurrency-in-elixir.html#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\\\/\\\/www.javacodegeeks.com\\\/2017\\\/02\\\/concurrency-in-elixir.html\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/2017\\\/02\\\/concurrency-in-elixir.html#primaryimage\",\"url\":\"https:\\\/\\\/www.javacodegeeks.com\\\/wp-content\\\/uploads\\\/2012\\\/10\\\/erlang-logo.jpg\",\"contentUrl\":\"https:\\\/\\\/www.javacodegeeks.com\\\/wp-content\\\/uploads\\\/2012\\\/10\\\/erlang-logo.jpg\",\"width\":150,\"height\":150},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/2017\\\/02\\\/concurrency-in-elixir.html#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\\\/\\\/www.javacodegeeks.com\\\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Software Development\",\"item\":\"https:\\\/\\\/www.javacodegeeks.com\\\/category\\\/software-development\"},{\"@type\":\"ListItem\",\"position\":3,\"name\":\"Concurrency in Elixir\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/#website\",\"url\":\"https:\\\/\\\/www.javacodegeeks.com\\\/\",\"name\":\"Java Code Geeks\",\"description\":\"Java Developers Resource Center\",\"publisher\":{\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/#organization\"},\"alternateName\":\"JCG\",\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\\\/\\\/www.javacodegeeks.com\\\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"en-US\"},{\"@type\":\"Organization\",\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/#organization\",\"name\":\"Exelixis Media P.C.\",\"url\":\"https:\\\/\\\/www.javacodegeeks.com\\\/\",\"logo\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/#\\\/schema\\\/logo\\\/image\\\/\",\"url\":\"https:\\\/\\\/www.javacodegeeks.com\\\/wp-content\\\/uploads\\\/2022\\\/06\\\/exelixis-logo.png\",\"contentUrl\":\"https:\\\/\\\/www.javacodegeeks.com\\\/wp-content\\\/uploads\\\/2022\\\/06\\\/exelixis-logo.png\",\"width\":864,\"height\":246,\"caption\":\"Exelixis Media P.C.\"},\"image\":{\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/#\\\/schema\\\/logo\\\/image\\\/\"},\"sameAs\":[\"https:\\\/\\\/www.facebook.com\\\/javacodegeeks\",\"https:\\\/\\\/x.com\\\/javacodegeeks\"]},{\"@type\":\"Person\",\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/#\\\/schema\\\/person\\\/d97c5de664686c98502d9f7e91603b44\",\"name\":\"Leigh Halliday\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/e6e9a38504203e4e08d6511cae4b60c40d54263cb22fcdab82d8bd4dcf92dd18?s=96&d=mm&r=g\",\"url\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/e6e9a38504203e4e08d6511cae4b60c40d54263cb22fcdab82d8bd4dcf92dd18?s=96&d=mm&r=g\",\"contentUrl\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/e6e9a38504203e4e08d6511cae4b60c40d54263cb22fcdab82d8bd4dcf92dd18?s=96&d=mm&r=g\",\"caption\":\"Leigh Halliday\"},\"description\":\"Leigh Halliday is a developer at Regalii. He writes about Ruby, Rails, and software development on his personal site.\",\"url\":\"https:\\\/\\\/www.javacodegeeks.com\\\/author\\\/leigh-halliday\"}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"Concurrency in Elixir - Java Code Geeks","description":"Erlang has been around for over 30 years and was built well before multi-core CPUs existed. Yet it\u2019s a language that couldn\u2019t be more relevant today! The","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/www.javacodegeeks.com\/2017\/02\/concurrency-in-elixir.html","og_locale":"en_US","og_type":"article","og_title":"Concurrency in Elixir - Java Code Geeks","og_description":"Erlang has been around for over 30 years and was built well before multi-core CPUs existed. Yet it\u2019s a language that couldn\u2019t be more relevant today! The","og_url":"https:\/\/www.javacodegeeks.com\/2017\/02\/concurrency-in-elixir.html","og_site_name":"Java Code Geeks","article_publisher":"https:\/\/www.facebook.com\/javacodegeeks","article_published_time":"2017-02-15T20:00:18+00:00","og_image":[{"width":150,"height":150,"url":"https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2012\/10\/erlang-logo.jpg","type":"image\/jpeg"}],"author":"Leigh Halliday","twitter_card":"summary_large_image","twitter_creator":"@javacodegeeks","twitter_site":"@javacodegeeks","twitter_misc":{"Written by":"Leigh Halliday","Est. reading time":"12 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/www.javacodegeeks.com\/2017\/02\/concurrency-in-elixir.html#article","isPartOf":{"@id":"https:\/\/www.javacodegeeks.com\/2017\/02\/concurrency-in-elixir.html"},"author":{"name":"Leigh Halliday","@id":"https:\/\/www.javacodegeeks.com\/#\/schema\/person\/d97c5de664686c98502d9f7e91603b44"},"headline":"Concurrency in Elixir","datePublished":"2017-02-15T20:00:18+00:00","mainEntityOfPage":{"@id":"https:\/\/www.javacodegeeks.com\/2017\/02\/concurrency-in-elixir.html"},"wordCount":1630,"commentCount":0,"publisher":{"@id":"https:\/\/www.javacodegeeks.com\/#organization"},"image":{"@id":"https:\/\/www.javacodegeeks.com\/2017\/02\/concurrency-in-elixir.html#primaryimage"},"thumbnailUrl":"https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2012\/10\/erlang-logo.jpg","keywords":["Elixir","Erlang"],"articleSection":["Software Development"],"inLanguage":"en-US","potentialAction":[{"@type":"CommentAction","name":"Comment","target":["https:\/\/www.javacodegeeks.com\/2017\/02\/concurrency-in-elixir.html#respond"]}]},{"@type":"WebPage","@id":"https:\/\/www.javacodegeeks.com\/2017\/02\/concurrency-in-elixir.html","url":"https:\/\/www.javacodegeeks.com\/2017\/02\/concurrency-in-elixir.html","name":"Concurrency in Elixir - Java Code Geeks","isPartOf":{"@id":"https:\/\/www.javacodegeeks.com\/#website"},"primaryImageOfPage":{"@id":"https:\/\/www.javacodegeeks.com\/2017\/02\/concurrency-in-elixir.html#primaryimage"},"image":{"@id":"https:\/\/www.javacodegeeks.com\/2017\/02\/concurrency-in-elixir.html#primaryimage"},"thumbnailUrl":"https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2012\/10\/erlang-logo.jpg","datePublished":"2017-02-15T20:00:18+00:00","description":"Erlang has been around for over 30 years and was built well before multi-core CPUs existed. Yet it\u2019s a language that couldn\u2019t be more relevant today! The","breadcrumb":{"@id":"https:\/\/www.javacodegeeks.com\/2017\/02\/concurrency-in-elixir.html#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/www.javacodegeeks.com\/2017\/02\/concurrency-in-elixir.html"]}]},{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/www.javacodegeeks.com\/2017\/02\/concurrency-in-elixir.html#primaryimage","url":"https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2012\/10\/erlang-logo.jpg","contentUrl":"https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2012\/10\/erlang-logo.jpg","width":150,"height":150},{"@type":"BreadcrumbList","@id":"https:\/\/www.javacodegeeks.com\/2017\/02\/concurrency-in-elixir.html#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/www.javacodegeeks.com\/"},{"@type":"ListItem","position":2,"name":"Software Development","item":"https:\/\/www.javacodegeeks.com\/category\/software-development"},{"@type":"ListItem","position":3,"name":"Concurrency in Elixir"}]},{"@type":"WebSite","@id":"https:\/\/www.javacodegeeks.com\/#website","url":"https:\/\/www.javacodegeeks.com\/","name":"Java Code Geeks","description":"Java Developers Resource Center","publisher":{"@id":"https:\/\/www.javacodegeeks.com\/#organization"},"alternateName":"JCG","potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/www.javacodegeeks.com\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"en-US"},{"@type":"Organization","@id":"https:\/\/www.javacodegeeks.com\/#organization","name":"Exelixis Media P.C.","url":"https:\/\/www.javacodegeeks.com\/","logo":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/www.javacodegeeks.com\/#\/schema\/logo\/image\/","url":"https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2022\/06\/exelixis-logo.png","contentUrl":"https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2022\/06\/exelixis-logo.png","width":864,"height":246,"caption":"Exelixis Media P.C."},"image":{"@id":"https:\/\/www.javacodegeeks.com\/#\/schema\/logo\/image\/"},"sameAs":["https:\/\/www.facebook.com\/javacodegeeks","https:\/\/x.com\/javacodegeeks"]},{"@type":"Person","@id":"https:\/\/www.javacodegeeks.com\/#\/schema\/person\/d97c5de664686c98502d9f7e91603b44","name":"Leigh Halliday","image":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/secure.gravatar.com\/avatar\/e6e9a38504203e4e08d6511cae4b60c40d54263cb22fcdab82d8bd4dcf92dd18?s=96&d=mm&r=g","url":"https:\/\/secure.gravatar.com\/avatar\/e6e9a38504203e4e08d6511cae4b60c40d54263cb22fcdab82d8bd4dcf92dd18?s=96&d=mm&r=g","contentUrl":"https:\/\/secure.gravatar.com\/avatar\/e6e9a38504203e4e08d6511cae4b60c40d54263cb22fcdab82d8bd4dcf92dd18?s=96&d=mm&r=g","caption":"Leigh Halliday"},"description":"Leigh Halliday is a developer at Regalii. He writes about Ruby, Rails, and software development on his personal site.","url":"https:\/\/www.javacodegeeks.com\/author\/leigh-halliday"}]}},"_links":{"self":[{"href":"https:\/\/www.javacodegeeks.com\/wp-json\/wp\/v2\/posts\/63878","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.javacodegeeks.com\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.javacodegeeks.com\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.javacodegeeks.com\/wp-json\/wp\/v2\/users\/1300"}],"replies":[{"embeddable":true,"href":"https:\/\/www.javacodegeeks.com\/wp-json\/wp\/v2\/comments?post=63878"}],"version-history":[{"count":0,"href":"https:\/\/www.javacodegeeks.com\/wp-json\/wp\/v2\/posts\/63878\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.javacodegeeks.com\/wp-json\/wp\/v2\/media\/113"}],"wp:attachment":[{"href":"https:\/\/www.javacodegeeks.com\/wp-json\/wp\/v2\/media?parent=63878"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.javacodegeeks.com\/wp-json\/wp\/v2\/categories?post=63878"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.javacodegeeks.com\/wp-json\/wp\/v2\/tags?post=63878"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}