概述

之前学习的 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/

elixir 高可用系列(四) Task的更多相关文章

  1. elixir 高可用系列 - 目录

    1. elixir 高可用系列(一) Agent 2. elixir 高可用系列(二) GenServer 3. elixir 高可用系列(三) GenEvent 4. elixir 高可用系列(四) ...

  2. elixir 高可用系列(五) Supervisor

    概述 OTP 平台的容错性高,是因为它提供了机制来监控所有 processes 的状态,如果有进程出现异常, 不仅可以及时检测到错误,还可以对 processes 进行重启等操作. 有了 superv ...

  3. elixir 高可用系列(三) GenEvent

    概述 GenEvent 是事件处理的通用部分的抽象. 通过 GenEvent ,我们给已有的服务 动态 的添加 事件处理. GenEevent 和 GenServer 的区别 之前已经介绍了 GenS ...

  4. elixir 高可用系列(二) GenServer

    概述 如果我们需要管理多个进程,那么,就需要一个专门的 server 来集中监控和控制这些进程的状态,启停等. OTP 平台中的 GenServer 就是对这个 server 通用部分的抽象. 利用 ...

  5. elixir 高可用系列(一) Agent

    概述 elixir 本身是一种 immutable 的语言,默认情况下,进程间是不共享任何状态的,进程之间通过消息来交互. 而 Agent 则封装了一种进程间共享状态的方式,通过这种方式,不用显式的写 ...

  6. (5.8)mysql高可用系列——MySQL中的GTID复制(实践篇)

    一.基于GTID的异步复制(一主一从)无数据/少数据搭建 二.基于GTID的无损半同步复制(一主一从)(mysql5.7)基于大数据量的初始化 正文: [0]概念 [0.5]GTID 复制(mysql ...

  7. keepalived高可用系列~ keepalived+proxysql

    一 简介:介绍下高可用通用的方案 二 目的:一个中间件提供服务,故障后,另一个中间件提供服务 三 手段: 应用keepalived的vrrp_scripts服务 四 具体配置 global_defs ...

  8. keepalived高可用系列~keepalived+mysql

    一 简介:建立读写分离模式 二 keepalived相关配置 vrrp_instance VI_1 {  state MASTER  // 可修改  interface eth0  virtual_r ...

  9. keepalived高可用系列~通用基础

    简介:今天咱们来聊聊keepalived一 keepalived 架构 1  标准架构: keepalived+lvs/haproxy+后端 real server(mysql从库,nginx.myc ...

随机推荐

  1. java三大框架之一hibernate使用入门

    综述:Hibernate的作用就是让实体类与数据库映射,使数据持久化,用于替代JDBC,使我们不致于写那么多sql语句代码. 1. 首先在官网www.hibernate.org下载hibernate包 ...

  2. modelsim(1) - 安装和使用 心得

    最近一段时间使用modelsim, 一,安装 使用的时候,出现license验证不对. 由于经常换虚拟机,要注意首先MAC地址是否换了,如果换了,license要重新做! 其次/etc/hosts的I ...

  3. 在linux上使用交换文件扩展交换空间

    想像一种情景,当我们的Linux系统用尽交换空间时,在这种情况下,我们想要使用swap分区扩展交换空间,但在某些情况下磁盘上已经没有可用的空闲分区了,致使我们不能把它扩大. 因此,在这种情况下,我们可 ...

  4. Android源代码结构分析

    Google提供的Android包含了:Android源代码,工具链,基础C库,仿真环境,开发环境等,完整的一套.第一级别的目录和文件如下所示:----------------├── Makefile ...

  5. Python全栈---5.1---装饰器

    一.装饰器 执行outer函数,将index作为参数传递, 将outer函数的返回值,重新赋值给index 装饰器可以在函数执行前和执行后执行其他的附加功能,这种在代码运行期间动态增加功能的方式,称之 ...

  6. 对需要聚类的数据使用canopy做初步的计算

    K值聚类的时候,需要自己指定cluster的数目. 这个cluster数目一般是通过canopy算法进行预处理来确定的. canopy具体描述可以参考这里. 下面是 golang语言的一个实现(对经纬 ...

  7. Python:迭代器

    迭代器:可以被next()函数调用并不断返回下一个值的对象称为迭代器. 可迭代对象:可以直接作用于for循环的对象. 基本方法:iter()和next() 迭代器创建: 例1: list = ['a' ...

  8. Hessian 初探

    Hessian 是一个序列化协议, 他的优点在于比 Java 原生的对象序列化/反序列化速度更快, 序列化出来以后的数据更小. 序列化协议跟应用层协议无关, 可以将 Hessian 序列化以后的数据放 ...

  9. zabbix网络发现

    zabbix的网络自动发现是一个非常强大的功能,该功能可以完成以下工作 •快速发现并添加主机. •简单的管理. •随着环境的改变而快速搭建监控系统. 网络发现基于以下信息 •ip地址段 •基于服务的F ...

  10. 2015年九月八日---js学习总结

    参考书:javaScript Dom 编程的艺术 知识小结:一:js简史:前称ECMAScript 是一种脚本语言通常只能通过浏览器进行解释和执行. Dom(文档对象模型):是一套对文档的内容进行抽象 ...