我正在编写一个ruby程序,它将使用线程来完成一些工作。正在完成的工作需要非确定的时间来完成,范围可以是5到45秒。下面是线程代码的粗略示例:
loop do # Program loop
items = get_items
threads = []
for item in items
threads << Thread.new(item) do |i|
# do work on i
end
threads.each { |t| t.join } # What happens if this isn't there?
end
end
我的偏好是跳过加入线程而不是阻止整个应用程序。但是我不知道这是什么长期影响,特别是因为代码几乎立即再次运行。这是安全的吗?或者是否有更好的方法来生成一个线程,让它工作,并在它完成后清理,所有这些都在一个无限循环中?
答案 0 :(得分:3)
我认为这实际上取决于你的线程工作的内容。例如,如果您的主线程需要打印“X work done”,您需要加入以确保您显示正确的答案。如果您没有这样的要求,那么您不一定需要加入。
答案 1 :(得分:2)
在写完问题之后,我意识到这是Web服务器在提供页面时所做的事情。我用Google搜索并找到了Ruby web server的以下文章。循环代码看起来非常像我的:
loop do
session = server.accept
request = session.gets
# log stuff
Thread.start(session, request) do |session, request|
HttpServer.new(session, request, basePath).serve()
end
end
Thread.start
is effectively the same为Thread.new
,因此看起来让线程完成并死掉是可以的。
答案 2 :(得分:1)
如果您将工作负载拆分为多个不同的线程,并且您需要在最后组合来自不同线程的解决方案,您肯定需要加入,否则您可以在没有连接的情况下进行此操作。
答案 3 :(得分:1)
如果您删除了join
,那么最终新项目的启动速度可能会比旧版本更快完成。如果您同时处理太多项目,可能会导致性能问题。
您应该使用队列(来自http://ruby-doc.org/stdlib/libdoc/thread/rdoc/classes/Queue.html的代码段):
require 'thread'
queue = Queue.new
producer = Thread.new do
5.times do |i|
sleep rand(i) # simulate expense
queue << i
puts "#{i} produced"
end
end
consumer = Thread.new do
5.times do |i|
value = queue.pop
sleep rand(i/2) # simulate expense
puts "consumed #{value}"
end
end
consumer.join