如何等待线程通知而不是加入所有线程?

时间:2013-12-19 13:08:59

标签: ruby multithreading

简而言之,用户向我的Web服务发出请求,我必须将请求转发给X个不同的API。我应该在并行上进行,所以我正在为此创建线程,并且第一个使用有效响应回答的线程,我应该杀死剩下的线程并立即回复给我的客户。

Ruby中的一个常见模式是创建多个线程,如

threads << Thread.new {}
threads.each { |t| t.join }

我已经拥有的逻辑是:

results = []
threads = []
valid_answer = nil

1.upto(10) do |i|
  threads = Thread.new do
    sleep(rand(60))
    results << i
  end
end

threads.each { |t| t.join }

valid_answer = results.detect { |r| r > 7 }

但是在前面的代码中,我阻止了这个过程,直到所有的线程完成。可能是一个线程将在1秒内回复并返回有效答案(所以此时我应该杀死所有其他线程并回复该答案),但相反,我加入所有线程并且不会太有道理了。

有没有办法在ruby中睡觉或等到一个线程回答,检查答案是否有效,然后再次阻塞/休眠直到所有线程都完成,或者直到其中一个线程给我一个有效的响应?


编辑:

应该并行完成。当我收到客户的请求时,我可以将请求转发给5家不同的公司。

每家公司的最长可达60秒(疯狂但真实的医疗保健业务)。

一旦这些公司中的一个回答,我必须检查响应(如果它是真实的响应或错误),如果它是真实的响应,我应该杀死所有其他线程并立即回答客户(没有理由让他等待60秒,如果其中一个请求让我恢复超时)。此外,没有理由在循环中进行它(就像我在循环中这样做,在最坏的情况下它会像5 x 60秒)。

1 个答案:

答案 0 :(得分:1)

也许让主线程睡眠?

def do_stuff
  threads = []
  valid_answer = nil

  1.upto(10) do |i|
    threads << Thread.new do
      sleep(rand(3))
      valid_answer ||= i if i > 7
    end
  end

  sleep 0.1 while valid_answer.nil?
  threads.each { |t| t.kill if t.alive? }
  valid_answer
end

编辑:唤醒也有更好的方法:

def do_stuff
  threads = []
  answer = nil

  1.upto(10) do |i|
    threads << Thread.new do
      sleep(rand(3))
      answer ||= i and Thread.main.wakeup if i > 7
    end
  end

  sleep
  threads.each { |t| t.kill if t.alive? }
  answer
end