2009-06-27 15 views
8

Ho vissuto nel mondo C++ per anni e sto appena iniziando con Ruby. Ho una lezione che mi piacerebbe fare una discussione. In Ruby è sbagliato derivare una classe da Thread? Gli esempi che vedo usano il concetto qui sotto.Classe derivata per thread rubino?

Thread.new { <some block> } 

Sarebbe sbagliato farlo?

class MyThread < Thread 
    def initialize 
    end 

    def run 
    <main loop> 
    end 

risposta

9

Penso che questa sia davvero una domanda sulla modellazione di domini.

Non ci sarebbe nulla di sbagliato in ciò che si sta facendo se si desidera estendere/migliorare il modo in cui si comporta un thread, ad esempio per aggiungere debug o output di prestazioni, ma non penso che sia ciò che si desidera.

Probabilmente vuoi modellare qualche concetto nel tuo dominio con oggetti attivi. In tal caso, l'approccio standard di Ruby è migliore perché consente di ottenere questo risultato senza piegare il modello di dominio.

L'ereditarietà dovrebbe essere utilizzata solo per modellare le relazioni IS_A. Il codice rubino standard per questo avvolge perfettamente la soluzione.

Per rendere il vostro oggetto attivo, hanno esso cattura il filo appena creato in un certo metodo

Class MyClass 

... 


    def run 
     while work_to_be_done do 
     some_work 
     end 
    end 

... 

end 


threads = [] 

# start creating active objects by creating an object and assigning 
# a thread to each 

threads << Thread.new { MyClass.new.run } 

threads << Thread.new { MyOtherClass.new.run } 

... do more stuff 

# now we're done just wait for all objects to finish .... 

threads.each { |t| t.join } 


# ok, everyone is done, see starships on fire off the shoulder of etc 
# time to die ... 
+0

Puoi descrivere quale sarebbe l'approccio standard di Ruby? Sarebbe solo passare un blocco di codice all'oggetto Thread? –

+0

Sì - Thread.new {do_stuff} è l'approccio più comune che ho visto. –

+0

Ho aggiornato la mia risposta con un esempio di oggetto attivo –

6

Va perfettamente bene, ho visto persone farlo prima. Ecco qualche esempio di codice da una delle mailing list di Ruby che viene eseguito quando viene chiamato Thread.new:

class MyThread < Thread 
    def initialize 
    super("purple monkey dishwasher") {|str| puts "She said, '#{str}.'"} 
    end 
end 

Se hai intenzione di chiamare Thread.fork o Thread.start per eseguire il filo, si dovrebbe essere consapevoli di questo dal Ruby documentation those methods:

". in pratica lo stesso di Discussione :: nuova Tuttavia, se classe thread è una sottoclasse, quindi chiamando inizio in quella sottoclasse sarà non richiamare il metodo di inizializzazione della sottoclasse"

+0

immagino il programmatore C++ è venuta fuori in me. Va bene in Ruby far uscire il thread dal costruttore? In genere, ciò non sarebbe mai stato fatto in C++. – nathan

+0

Sono d'accordo che è un po 'strano, ma mette in risalto la flessibilità che Ruby ti offre. E 'questa una buona idea? È un po 'strano, ma è certamente consentito dalla classe e dalla lingua, ed è molto leggibile. Altri hanno sottolineato che questa non è la cosa standard da fare, ma non penso che sia la cosa peggiore di sempre, e potrebbe esserci un'applicazione per cui questo è perfetto. –

+0

+1 Per la tua risposta, James. Hai risposto alla domanda fatta. Chris in realtà mi ha fatto capire che stavo avendo un problema di dominio. Quindi la risposta premiata va a lui. – nathan

0

Non è davvero il modo in cui rubino, ma dipende da ciò che si sta cercando di realizzare con il filo.

Prima di tutto, Ruby 1.8 non ha realmente thread reali, quindi sono davvero utili solo per le cose legate all'IO.

Generalmente in ruby ​​si desidera che qualcosa esegua un'azione in una discussione anziché rappresentare un thread, quindi è più semplice definire una classe ordinaria che crea thread all'interno per gestire l'aspetto della filettatura.

L'ereditarietà è una relazione is_a

1

Il filo Rubino documentazione parla di "Se il filo è una sottoclasse" così sembra come dovrebbe andare bene. Assicurati che se la tua sovrascrittura si inizializza, chiami super!

5

io preferisco fare l'incapsulamento in tal modo:

class Threader 
    def initialize 
    @thread = Thread.new(&method(:thread)) 
    end 

private 

    def thread 
    # Do thready things... 
    end 
end 

si potrebbe anche farlo direttamente ad una sottoclasse Discussione:

class ThreadyThread < Thread 
    def initialize 
    super(&method(:thread)) 
    end 

private 

    def thread 
    # Do thready things... 
    end 
end 
+0

+1 grazie per l'idea. Ho sempre pensato che la definizione del blocco del thread fosse pericolosa perché l'oscilloscopio del chiamante fuoriesce dal blocco. Questo è molto più pulito e incapsulato. – Kelvin

+0

Questo è quello che stavo cercando. Molto meglio incapsulato e organizzato. Grazie! – hbobenicio

Problemi correlati