2013-12-19 32 views
0

简而言之,用户向我的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秒内回答一个有效的答案(所以在这一点上,我应该杀死所有其他线程并回报该答案),但是相反,我加入所有线程并且不会使太有意义了。

有没有一种方法让红宝石睡觉或等到一个线程回答,检查该回答是否有效,然后再次阻塞/休眠,直到所有线程完成或者直到其中一个线程返回有效响应?


编辑:

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

每家公司可能会有超过60秒的时间(疯狂但真实的医疗保健业务)。

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

+0

你的问题听起来更是一个循环的线程。等待正确的事情并开始另一个请求是一个循环,你会做什么并行? – devanand

+0

我刚刚做了一个编辑,解释了我遇到的问题以及我在不同线程上需要所有这一切的原因。 – rorra

回答

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 
+0

很酷,这将工作,我正在寻找一个系统调用来阻止进程,直到一个线程通知我它准备好或类似的东西,但你的代码是务实的,它会解决我的问题:)我也应该确保一个的线程是至少运行或返回一个错误,但它的一个小的更新,thx再次:) – rorra

+0

我怀疑有一种方法可以用throw/catch块来做到这一点。 –

+1

更好的方法是使用'wakeup'(请参阅我的编辑)。 –