当您不加入线程时会发生什么?

5

我正在编写一个使用线程执行一些工作的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

我的偏好是跳过加入线程并且不阻塞整个应用程序。但是我不知道这样做的长期影响,特别是因为代码几乎立即再次运行。这样做是否安全?或者有更好的方法来生成一个线程,在无限循环中让它工作,并在完成后清理?

4个回答

3

我认为这取决于你的线程工作内容。例如,如果你的主线程需要打印“X工作已完成”,那么你需要使用join来确保显示正确的答案。如果没有这样的要求,那么你就不一定需要使用join。


2
写完问题后,我意识到这正是Web服务器在提供页面时所做的事情。我谷歌了一下,找到了一个Ruby Web服务器的文章。循环代码看起来与我的差不多。
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 实际上等同于 Thread.new,因此让线程完成并死亡似乎是可以的。


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

@Gavin:文档提到了线程,而该类来自thread.rb。但是,它没有使用“线程安全”一词。如果你希望他们明确表示它是线程安全的,我可以提交一个文档错误报告。 - Andrew Grimm
我没有注意到它来自thread.rb,这对我来说已经足够证明了!我通常使用.NET编程,因此习惯于显式地区分“这是线程安全的”和“这不是线程安全的”。 - Gavin Miller

1
如果您将工作负载分配给几个不同的线程,并且需要在最后合并来自不同线程的解决方案,则绝对需要一个join,否则您可以在没有join的情况下完成它。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接