我如何终止监督组?

时间:2014-04-30 15:24:21

标签: ruby multithreading rubinius celluloid

我在Celluloid中实现了一个简单的程序,理想情况下会并行运行一些actor,每个actor都会计算一些东西,然后将其结果发送回一个主要角色,其主要工作就是聚合结果

关注this FAQ,我引入了SupervisionGroup,如下所示:

module Shuffling           
  class AggregatorActor
    include Celluloid      

    def initialize(shufflers)
      @shufflerset = shufflers
      @results = {}        
    end

    def add_result(result)
      @results.merge! result

      @shufflerset = @shufflerset - result.keys

      if @shufflerset.empty?
        self.output
        self.terminate
      end
    end

    def output
      puts @results
    end
  end

  class EvalActor
    include Celluloid

    def initialize(shufflerClass)
      @shuffler = shufflerClass.new
      self.async.runEvaluation
    end

    def runEvaluation
      # computation here, which yields result
      Celluloid::Actor[:aggregator].async.add_result(result)
      self.terminate
    end
  end

  class ShufflerSupervisionGroup < Celluloid::SupervisionGroup
    shufflers = [RubyShuffler, PileShuffle, VariablePileShuffle, VariablePileShuffleHuman].to_set

    supervise AggregatorActor, as: :aggregator, args: [shufflers.map { |sh| sh.new.name }]

    shufflers.each do |shuffler|
      supervise EvalActor, as: shuffler.name.to_sym, args: [shuffler]
    end
  end

  ShufflerSupervisionGroup.run
end

我完成后终止了EvalActor,并在完成所有工作后终止AggregatorActor

然而,监督线程保持活跃并使主线程保持活动状态。该程序永远不会终止。

如果我向组发送.run!,那么主线程就会在它之后终止,并且没有任何效果。

finalize终止后,我可以做什么来终止群组(或者,在群组术语中,AggregatorActor)?

1 个答案:

答案 0 :(得分:0)

我所做的是将AggregatorActor更改为wait_for_results

class AggregatorActor
  include Celluloid

  def initialize(shufflers)
    @shufflerset = shufflers
    @results = {}
  end

  def wait_for_results
    sleep 5 while not @shufflerset.empty?

    self.output
    self.terminate
  end

  def add_result(result)
    @results.merge! result

    @shufflerset = @shufflerset - result.keys

    puts "Results for #{result.keys.inspect} recorded, remaining: #{@shufflerset.inspect}"
  end

  def output
    puts @results
  end
end

然后我摆脱了SupervisionGroup(因为我不需要监督,即重新运行失败的演员),我就这样使用它了:

shufflers = [RubyShuffler, PileShuffle, VariablePileShuffle, VariablePileShuffleHuman, RiffleShuffle].to_set

Celluloid::Actor[:aggregator] = AggregatorActor.new(shufflers.map { |sh| sh.new.name })

shufflers.each do |shuffler|
  Celluloid::Actor[shuffler.name.to_sym] = EvalActor.new shuffler
end

Celluloid::Actor[:aggregator].wait_for_results

感觉不是很干净,如果有更清洁的方式会很好,但至少这样可行。