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

时间:2021-07-30 20:40:28

In few words, a user makes a request to my web service, and I have to forward the request to X different APIs. I should do it on parallel, so I'm creating threads for this, and the first Thread that answers with a valid response, I should kill the rest of the threads and give back the answer to my customer right away.

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

One common pattern in Ruby, is to create multiple threads like

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

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

The logic I already have is something like:

我已经拥有的逻辑是这样的:

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 }

But on a code like the previous, I'm blocking the process until all of the threads finish. It could be that one thread will answer back in 1 second with a valid answer (so at this point I should kill all the other threads and give back that answer), but instead, I'm joining all the threads and doesn't make too much sense.

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

Is there a way in ruby to sleep or wait until one thread answer, check if that answer is valid, and then blocking/sleeping again until all of the threads are done or either until one of them gives me back a valid response?

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


Edit:

It should be done in parallel. When I get a request from the customer, I can forward the request to 5 different companies.

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

Each company can have a timeout up to 60 seconds (insane but real, healthcare business).

每家公司都可以暂停60秒(疯狂但真实的医疗保健业务)。

As soon as one of these companies answer, I have to check the response (if its a real response or an error), if its a real response, I should kill all of the other threads and answer the customer right away (no reason to make him to wait for 60 seconds if one of the requests gives me back a timeout). Also, no reason to make it on a loop (like if I do this on a loop, it would be like 5 x 60 seconds in the worst scenario).

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

1 个解决方案

#1


1  

Perhaps by making the main thread sleep?

也许是通过让主线程睡眠?

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

Edit: there is a better approach with wakeup, too:

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

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

#1


1  

Perhaps by making the main thread sleep?

也许是通过让主线程睡眠?

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

Edit: there is a better approach with wakeup, too:

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

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