2010-11-04 2 views
4

J'écris un programme ruby ​​qui utilisera des threads pour travailler. Le travail en cours prend une durée non déterministe et peut durer de 5 à 45 secondes. Ci-dessous un exemple de ce que le rugueux code threading ressemble:Que se passe-t-il lorsque vous ne rejoignez pas vos threads?

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 

Ma préférence serait de sauter joindre les fils et ne bloque pas l'application. Cependant, je ne sais pas quelles en sont les implications à long terme, notamment parce que le code est exécuté presque immédiatement. Est-ce quelque chose qui est sûr de faire? Ou y a-t-il une meilleure façon de générer un thread, de le faire fonctionner, et de le nettoyer quand c'est fini, le tout dans une boucle infinie?

Répondre

2

Après avoir écrit la question, je me suis rendu compte que c'est exactement ce que fait un serveur web lorsqu'il sert des pages. J'ai googlé et trouvé l'article suivant d'un Ruby web server. Le code de la boucle ressemble beaucoup à la mienne:

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.startis effectively the same comme Thread.new, il semble donc que laisser les fils finition et meurent est OK pour faire.

3

Je pense que cela dépend vraiment du contenu de votre travail de thread. Si, par exemple, votre thread principal avait besoin d'imprimer "X work done", vous devrez vous joindre pour garantir que vous montriez la bonne réponse. Si vous n'avez pas une telle exigence, vous n'aurez pas nécessairement besoin de vous joindre.

+1

Les fils ne ont pas besoin de faire rapport au programme principal. –

1

Si vous découpez une charge de travail à plusieurs threads différents et vous devez combiner à la fin les solutions des différents sujets dont vous avez besoin sans aucun doute une jointure sinon vous pouvez le faire sans se joindre ..

1

Si vous avez supprimé le join, vous pourriez vous retrouver avec de nouveaux éléments à démarrer plus rapidement que les plus anciens. Si vous travaillez sur un trop grand nombre d'éléments à la fois, cela peut entraîner des problèmes de performances.

Vous devez utiliser une file d'attente à la place (extrait de 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 
+0

Les files d'attente de Ruby sont-elles sûres? –

+0

@Gavin: La documentation mentionne les threads, et la classe provient de 'thread.rb'. Cependant, il n'utilise pas les mots "thread safe". Si vous préférez qu'ils disent explicitement que le thread est sûr, je pourrais déposer un bug de documentation. –

+0

Je n'ai pas compris que ça vient de 'thread.rb', c'est une preuve suffisante pour moi! Je programme normalement en .NET, donc je suis habitué à ce qui est explicite "c'est thread-safe" vs "ce n'est pas thread-safe" –

Questions connexes