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

Posted

技术标签:

【中文标题】如何等待线程通知而不是加入所有线程?【英文标题】:How to wait for Thread notification instead of joining all the Threads? 【发布时间】:2013-12-19 13:08:58 【问题描述】:

简而言之,用户向我的 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】:

也许通过让主线程休眠?

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

【讨论】:

酷,这会起作用,我正在寻找一个系统调用来阻止进程,直到一个线程通知我它准备好或类似的东西,但是你的代码是实用的,它将解决我的问题:)我还应该确保其中一个线程至少正在运行或返回一个错误,但它是一个小更新,再次感谢 :) 我怀疑也有一种方法可以使用 throw/catch 块。 酷,我在找那个,不知道唤醒方法,它会让我睡觉,直到一个线程通知我它准备好了,谢谢。

以上是关于如何等待线程通知而不是加入所有线程?的主要内容,如果未能解决你的问题,请参考以下文章

主程序如何通过等待而不是加入同时等待多个线程?

通知线程是不是可以在被通知线程等待锁定之前锁定?

等待条件的线程的有序通知(C++,boost)

如何在静态上下文中等待线程?

线程 等待/通知机制

线程的等待和通知及示例代码(waitnotifynotifyAll)