Что происходит, когда вы не присоединяетесь к своим темам? - PullRequest
4 голосов
/ 04 ноября 2010

Я пишу программу 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 голосов
/ 04 ноября 2010

Я думаю, что это действительно зависит от содержания вашей работы с потоками.Если, например, ваш основной поток должен был напечатать «X work done», вам необходимо присоединиться, чтобы гарантировать, что вы показываете правильный ответ.Если у вас нет таких требований, вам не обязательно присоединяться.

2 голосов
/ 04 ноября 2010

После написания вопроса я понял, что это именно то, что веб-сервер делает при обслуживании страниц.Я гуглил и нашел следующую статью о веб-сервере Ruby .Код цикла выглядит примерно так же, как у меня:

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 голос
/ 05 ноября 2010

Если вы удалите 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
1 голос
/ 04 ноября 2010

Если вы разделите рабочую нагрузку на несколько разных потоков, и вам нужно объединить в конце решения из разных потоков, вам определенно понадобится объединение, в противном случае вы можете сделать это без объединения.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...