zoukankan      html  css  js  c++  java
  • elixir 高可用系列(四) Task

    概述

    之前学习的 Agent,GenSever以及GenEvent,都是用来管理状态或者处理消息的。
    但是在很多时候,我们需要的是执行某个任务,这时如果使用 GenSever 或者 GenEvent,就会显得比较笨重。

    这时,我们就可以使用 Task 模块,使用 Task 模块时注意以下几点:

    1. 每个 task 只执行一个特定的功能,要让 task 处理的业务尽量简单(如果业务复杂的话,考虑使用 GenSever 或者 GenEvent)
    2. task 之间尽量不要交互,也尽量不要和其他 process交互 ,保持 task 的独立性

    task 最重要的特性是能够方便的将顺序执行的代码转变为并发执行的代码。

    task 示例

    示例一: 将顺序代码转为并发代码(类似多线程)

    defmodule TaskTest do
      def test_sync() do
        for n <- [1,2,3,4] do
          :timer.sleep(1000)
          IO.puts("it's #{n} #{TimeUtil.now}")
        end
      end
    
      def test_async() do
        for n <- [1,2,3,4] do
          Task.start_link(fn ->
            :timer.sleep(1000)
            IO.puts("it's #{n} #{TimeUtil.now}")
          end)
        end
      end
    
    defmodule TimeUtil do
      def now() do
        {{y,m,d}, {h,mm,s}} = :calendar.local_time
        "#{y}/#{m}/#{d} #{h}:#{mm}:#{s}"
      end
    end
    
    
    IO.puts "execute sync"
    TaskTest.test_sync
    IO.puts "==============================="
    IO.puts "execute async"
    TaskTest.test_async
    

    执行结果如下:

    iex(1)> r(TaskTest)
    execute sync
    it's 1 2016/5/31 13:53:2
    it's 2 2016/5/31 13:53:3
    it's 3 2016/5/31 13:53:4
    it's 4 2016/5/31 13:53:5
    ===============================
    execute async
    it's 1 2016/5/31 13:53:6
    it's 2 2016/5/31 13:53:6
    it's 3 2016/5/31 13:53:6
    it's 4 2016/5/31 13:53:6
    

    示例二:异步执行,并获取执行结果

    defmodule TaskTest do
    
      def exec_task() do
        t = Task.async(fn ->
          IO.puts("start to do something at #{TimeUtil.now}")
          :timer.sleep(3000)
        end)
        t
      end
    
      def get_task_result(t) do
        Task.await(t, 5000)
        IO.puts("get something result at #{TimeUtil.now}")
      end
    end
    
    defmodule TimeUtil do
      def now() do
        {{y,m,d}, {h,mm,s}} = :calendar.local_time
        "#{y}/#{m}/#{d} #{h}:#{mm}:#{s}"
      end
    end
    
    
    t = TaskTest.exec_task                     # 异步执行
    IO.inspect(TaskTest.get_task_result(t))    # 同步获取执行结果
    

    运行结果如下:

    iex(1)> r(TaskTest)
    start to do something at 2016/5/31 14:24:48
    get something result at 2016/5/31 14:24:51
    :ok
    

    注意 如果 get_task_result 中 Task.await 的超时时间设置的小于task的执行时间的话(比如await的时间由 5000 -> 2000),
    那么,会导致 get_task_result timeout的错误。

    总结

    从上面的例子可以看出,利用 Task 模块,可以很方便的实现并发和异步操作。
    但是,在用 task 执行任务的时候,我们发现,在并发和异步的环境中,如果某个 task 执行失败的话,甚至会导致主进程也失败。

    下一节的监督者机制,将介绍 elixir 如何利用 OTP平台 完美解决上述并发和异步中的问题。

    来源:http://blog.iotalabs.io/

  • 相关阅读:
    Restful API设计规范
    git merge 和 git merge --no-ff
    [Machine Learning & Algorithm] 朴素贝叶斯算法(Naive Bayes)
    TF-IDF与余弦相似性的应用(三):自动摘要
    TF-IDF与余弦相似性的应用(二):找出相似文章
    TF-IDF与余弦相似性的应用(一):自动提取关键词
    LeetCode 442. Find All Duplicates in an Array
    LeetCode 29. Divide Two Integers
    LeetCode 402. Remove K Digits
    LeetCode 406. Queue Reconstruction by Height
  • 原文地址:https://www.cnblogs.com/wang_yb/p/5545903.html
Copyright © 2011-2022 走看看