ruby块内的赛璐id异步不起作用

试图在我的工作实例上实现Celluloid异步似乎表现出奇怪的行为.

这里我的代码看起来

class Indefinite
    include Celluloid

      def run!
         loop do 
           [1].each do |i|
             async.on_background
           end
         end
      end 


       def on_background
         puts "Running in background" 
       end
   end

   Indefinite.new.run!

但是当我运行上面的代码,我从来没有看到放置“在后台运行”

但是,如果我睡觉,代码似乎工作.

class Indefinite
   include Celluloid

    def run! 
      loop do 
        [1].each do |i|
          async.on_background
        end
        sleep 0.5
      end 
    end


   def on_background
     puts "Running in background" 
   end
 end

 Indefinite.new.run!

任何想法?为什么在上述两种情况下有这样的区别.

谢谢.

解决方法

你的主要循环是主角/应用程序的线程.

你所有的程序正在做的是产生后台进程,但从不运行它们.你需要在循环中的睡眠才能让背景线程得到注意.

通过一个无条件的循环来产生无限的后台进程通常不是一个好主意,就像你在这里一样.应该有一个延迟或条件语句放在那里…否则你只有一个无限循环产生永远不会被调用的东西.

想像这样:如果你把循环放在你的循环中,而你没有看到在后台运行,你会看到循环一遍又一遍.

方法#1:使用每个或更多的块.

解决这个问题的最好方法是不要在循环中使用睡眠,而是使用一个或多个块,如下所示:

every(0.1) {
    on_background
}

或者最重要的是,如果要确保进程在运行前完全运行,请再次运行:

def run_method
    @running ||= false
    unless @running
        @running = true
        on_background
        @running = false
    end
    after(0.1) { run_method }
 end

使用循环不是异步的好主意,除非有某种流量控制完成,或者使用@ server.accept等阻塞过程,否则只会将100%的CPU内核没有任何理由.

顺便说一句,你也可以使用now_and_every以及now_and_after,这样也可以立即运行该块,然后在你想要的时间后再运行一次.

使用每一个都显示在这个要点中:

> https://gist.github.com/digitalextremist/686f42e58a58b743142b

理想情况,在我看来:

这是一个粗略但立即可用的示例:

> https://gist.github.com/digitalextremist/12fc824c6a4dbd94a9df

require 'celluloid/current'

class Indefinite
  include Celluloid

  INTERVAL = 0.5
  ONE_AT_A_TIME = true

  def self.run!
    puts "000a Instantiating."
    indefinite = new
    indefinite.run
    puts "000b Running forever:"
    sleep
  end

  def initialize
    puts "001a Initializing."
    @mutex = Mutex.new if ONE_AT_A_TIME
    @running = false
    puts "001b Interval: #{INTERVAL}"
  end

  def run
    puts "002a Running."
    unless ONE_AT_A_TIME && @running
      if ONE_AT_A_TIME
        @mutex.synchronize {
          puts "002b Inside lock."
          @running = true
          on_background
          @running = false
        }
      else
        puts "002b Without lock."
        on_background
      end
    end
    puts "002c Setting new timer."
    after(INTERVAL) { run }
  end


  def on_background
    if ONE_AT_A_TIME
      puts "003 Running background processor in foreground."
    else
      puts "003 Running in background"
    end
  end
end

Indefinite.run!
puts "004 End of application."

这将是其输出,如果ONE_AT_A_TIME为真:

000a Instantiating.
001a Initializing.
001b Interval: 0.5
002a Running.
002b Inside lock.
003 Running background processor in foreground.
002c Setting new timer.
000b Running forever:
002a Running.
002b Inside lock.
003 Running background processor in foreground.
002c Setting new timer.
002a Running.
002b Inside lock.
003 Running background processor in foreground.
002c Setting new timer.
002a Running.
002b Inside lock.
003 Running background processor in foreground.
002c Setting new timer.
002a Running.
002b Inside lock.
003 Running background processor in foreground.
002c Setting new timer.
002a Running.
002b Inside lock.
003 Running background processor in foreground.
002c Setting new timer.
002a Running.
002b Inside lock.
003 Running background processor in foreground.
002c Setting new timer.

如果ONE_AT_A_TIME为假,这将是其输出:

000a Instantiating.
001a Initializing.
001b Interval: 0.5
002a Running.
002b Without lock.
003 Running in background
002c Setting new timer.
000b Running forever:
002a Running.
002b Without lock.
003 Running in background
002c Setting new timer.
002a Running.
002b Without lock.
003 Running in background
002c Setting new timer.
002a Running.
002b Without lock.
003 Running in background
002c Setting new timer.
002a Running.
002b Without lock.
003 Running in background
002c Setting new timer.
002a Running.
002b Without lock.
003 Running in background
002c Setting new timer.
002a Running.
002b Without lock.
003 Running in background
002c Setting new timer.

您需要比“线程”更多地“发送”,以正确发出任务并保留范围和状态,而不是在线程/ actors之间发出命令,这是每个和每个块提供的内容.除此之外,无论哪种方式,即使您没有Global Interpreter Lock来处理这种做法也是一个很好的做法,因为在您的示例中,您似乎并不喜欢处理阻止进程.如果你有一个阻塞过程,那么一切都有一个无限循环.但是,由于您只是在处理之前最终产生无限数量的后台任务,所以您需要像开始使用您的问题一样使用睡眠,或者使用完全不同的策略,然后使用每一个Celloloid本身如何鼓励您在处理任何类型的插座上的数据时进行操作.

方法#2:使用递归方法调用.

这刚刚出现在Google集团.下面的示例代码实际上将允许执行其他任务,即使它是一个无限循环.

> https://groups.google.com/forum/#!topic/celluloid-ruby/xmkdrMQBGbY

这种方法不太可取,因为它可能会有更多的开销,产生一系列的纤维.

def work
    # ...
    async.work
end

问题2:线程与光纤行为.

第二个问题是为什么下面的工作:循环{Thread.new {puts“Hello”}}

这产生了无数个进程线程,由线程直接管理.即使您正在使用RVM中的全局解释器锁定,这仅意味着不会使用绿色线程,这些线程由操作系统本身提供,而是由进程本身处理.该进程的CPU调度程序会毫不犹豫地运行每个线程本身.在这个例子的情况下,线程运行非常快,然后死亡.

与异步任务相比,使用了光纤.所以发生的是这样的,在默认情况下:

>进程启动.
>演员实例化.
方法调用调用循环.
循环调用异步方法.
> async方法将任务添加到邮箱.
>邮箱不被调用,循环继续.
>另一个异步任务被添加到邮箱.
>这继续无限.

以上是因为循环方法本身是一个光纤呼叫,它不会被暂停(除非调用了一个睡眠!),因此添加到邮箱的附加任务决不是调用一个新的光纤.光纤的行为与线程不同.这是讨论差异的很好的参考资料:

> https://blog.engineyard.com/2010/concurrency-real-and-imagined-in-mri-threads

问题3:赛璐id与赛璐id :: ZMQ行为.

第三个问题是为什么Celluloid的行为与Celluloid :: ZMQ不同?

这是因为Celluloid :: ZMQ使用基于反应器的事件邮箱,而Celluloid使用基于条件变量的邮箱.

详细了解流水线和执行模式:

> https://github.com/celluloid/celluloid/wiki/Pipelining-and-execution-modes

这是两个例子之间的区别.如果您对这些邮箱的行为有其他问题,请随时在Google Group上发布…您所面临的主要动态是GIL与Fiber vs. Thread vs. Reactor行为相互作用的独特性质.

您可以在这里阅读有关反应堆模式的更多信息:

> http://en.wikipedia.org/wiki/Reactor_pattern
> Explanation of the “Reactor pattern”
> What is the difference between event driven model and reactor pattern?

并查看Celluloid :: ZMQ使用的特定反应器:

> https://github.com/celluloid/celluloid-zmq/blob/master/lib/celluloid/zmq/reactor.rb

那么在事件邮箱场景中发生的情况是,当打入睡眠时,这是一个阻塞调用,这将导致反应器移动到邮箱中的下一个任务.

而且,这是您的情况独特的,Celluloid :: ZMQ使用的特定反应堆正在使用一个永恒的C库,特别是0MQ库.该反应器在您的应用程序外部,其行为与Celluloid :: IO或Celluloid本身不同,这也是为什么行为发生与预期不同的原因.

多核支持选择

如果维护状态和范围对您不重要,如果使用不限于一个操作系统线程的jRuby或Rubinius,而使用具有全球解释器锁定的MRI,则可以实例化多个actor并在actor之间发出异步调用同时.

但我的谦虚的观点是,使用非常高频率的定时器,比如我的例子中的0.001或0.1,这对于所有意图和目的来说似乎是瞬间的,而且还允许演员线程有足够的时间来切换光纤并在邮箱中运行其他任务.

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


validates:conclusion,:presence=>true,:inclusion=>{:in=>[0,1]}validates:email,:presence=>true,:length=>{:minimum=>3,:maximum=>254},:uniqueness=>true,:email=>truevalidates:ending_order,
一、redis集群搭建redis3.0以前,提供了Sentinel工具来监控各Master的状态,如果Master异常,则会做主从切换,将Slave作为master,将master做为slave。其配置也较复杂,且表现一般。redis3.0以后已经支持集群容错功能,并且非常简单1.1素材准备centos7(集群搭建,至少三个master。需
分享一下我老师大神的人工智能教程。零基础!通俗易懂!风趣幽默!还带黄段子!希望你也加入到我们人工智能的队伍中来!https://blog.csdn.net/jiangjunshow                 不知道大家是否注意到,全新安装ruby之后,无论是在windows或是linux还是macosX下使用rix
上一篇博文 ruby传参之引用类型 里边定义了一个方法名 modify_my_object!,这个方法名是以!结尾,在ruby的对象里边是用于表达修改本身的意思。比如String#gsub,返回的是一个新的字符串对象;而String#gsub!,返回的是自身已经被修改的对象。不止!这样的特殊字符可以命名,ruby
一编程与编程语言 什么是编程语言? 能够被计算机所识别的表达方式即编程语言,语言是沟通的介质,而编程语言是程序员与计算机沟通的介质。 什么是编程? 编程即程序员根据需求把自己的思想流程按照某种编程语言的语法风格编写下来,产出的结果就是包含一堆字符的文件。二编程语言分
Ruby类和对象Ruby是一种完美的面向对象编程语言。面向对象编程语言的特性包括:数据封装数据抽象多态性继承这些特性将在面向对象的Ruby中进行讨论。一个面向对象的程序,涉及到的类和对象。类是个别对象创建的蓝图。在面向对象的术语中,您
1.ruby的标签<ruby>漢<rp>(<p><rt>han<t><rp>)<p>字<rp>(<p><rt>zi<t><rp>)<p><uby> 
1、软件安装1.安装包是个压缩包-->解压到/homeedis_tar下命令如下: tar-zxvf./../-C/homeedis_tar2.安装c++环境yum-yinstallgcc-c++(注:redis底层源码是c++)3.解压后需要源码编译进入到redis-3.0.0后执行make4.编译完后开始安装需要指定一个安装路径
1.sass基于Ruby语言开发而成,因此安装sass前需要安装Ruby。(注:mac下自带Ruby无需在安装Ruby!)window下安装SASS首先需要安装Ruby,先从官网下载Ruby并安装。安装过程中请注意勾选AddRubyexecutablestoyourPATH添加到系统环境变量。ruby官网:https:/ubyinstaller.org/downloa
本节对我们项目实现的功能和知识点做一个简单的介绍,因为是RESTfulAPI项目,所以对于后端来说基本上没有什么UI界面可展示,那我们就在关键的点,使用客户端(Android)实现的效果图。课程简介这是一门企业级项目实战课程,目的是从0使用Rails开发一个企业级RESTfulAPI项目;他不能让你年薪30
注意点:1.redis集群至少需要6个节点。2.redis集群至少部署在3台服务器上。3.redis的版本需要在3.0以上。4.需要ruby的支持。步骤:1.安装依赖环境:yuminstallgcc-c++2.下载ruby-2.4.6,编译安装https://cache.ruby-lang.org/pububy/2.4uby-2.4.6.tar.gztarzxf ruby-2.4.6.
在我的客户项目中,我看到很多睡眠用法0.代码看起来像这样.whiletrue......sleep0end通过阅读SO的一些答案,如this,似乎睡眠0具有一定的意义.我现在想知道的是,在时间片0期间调度其他线程运行(如果它们正在等待运行)是像ruby或python这样的langVM的工作,或者它
前情提要:第11天开始,要更深入Ruby的精髓!Ruby经典面试题目#11Ruby的block,proc,lamdba方法比较?What’sdifferencebetweenblocks,procsandlambdas?block代码内存块代码内存块是用do…end围起来,围出特定一个区域、放代码的地方。就好像跑马拉松一样,道路上会进行交通管制,把参赛者
安装环境及工具系统:RedHatEnterpriseLinuxServer工具:XShell5及Xftp5等远程工具安装包:Ruby-2.4.1及以上       Rubygems-2.6.12及以上       Redis-3.2.8及以上(3.x版本才开始支持集群功能)       Redis-3.0.0-gem及以上(该版本不一定要和red
 今天在做Redis的Cluster集群的时候,在执行geminstallredis时,提示如下错误:geminstallredisERROR:Errorinstallingredis:redisrequiresRubyversion>=2.2.2.CentOS7yum库中ruby的版本支持到2.0.0,可gem安装redis需要最低是2.2.2,采用rvm来更新ruby:1
我试图在Rails4中制作应用程序.我正在挣扎.我正在尝试合并一个bootstrap主题,我遇到了供应商javascripts和其余代码的问题.我认为问题可能与在我的application.js中使用jQuery然后使用以’$’符号开头的供应商.js文件有关:$.circleProgress={我刚看过这个:https://learn.jqu
该内容全部为搬运,感谢作者的分享~,附有原文链接。使用ruby环境SASS学习系列之(一)---------SASS,SCSS环境搭建(Ruby) 使用node-sassSASS学习系列之(二)---------SASS,SCSS环境搭建(node-sass)通过命令编译:npmrunsassinput.scssoutput.csssass-loader在webpack打包里
我如何使用PHP5.3Closures,比如我们在Ruby中使用Blocks.我从来没有在Ruby中使用’for’循环,因为使用带有’each”read_all”inject’方法的块.我如何使用像Ruby块这样的PHP5.3闭包,并说再见’for’Loops
一、说明:搭建Redis集群时,安装geminstallredis报错: redisrequiresRubyversion>=2.2.2的报错,查了资料发现是Centos默认支持ruby到2.0.0,可gem安装redis需要最低是2.2.2二、解决办法:解决办法是先安装rvm,再把ruby版本提升至2.3.31.安装curlsudoyuminstal
compass.app是集成了sass的工具,安装完Compass就能够使用sass。首先,上官网 可以看到官网上推荐的两种sass使用方式,application&commandlineapplication里不仅仅只有Compass,不过现在点击Compass.app进行下载。虽然通常我们说sass运行在Ruby环境下,但Compass.app安装使用并不需要