2010-02-27 6 views
8

erste:Zwei Fragen Ruby verwandte Themen

  • wie kann ich erstellen einen Thread, der nicht richtig away.If ich ohne Block eine Ausnahme wird angehoben verwenden initialize beginnt.

  • Wie kann ich Thread ableiten, so dass ich einige benutzerdefinierte Attribute hinzufügen kann, aber die gleiche Funktionalität wie die Basis-Thread-Klasse beibehalten? Ich möchte auch nicht die initialize(&block) Methode dafür verwenden müssen.

Um dies besser zu veranschaulichen:

Für die erste Frage:

x = Thread.new 
x.run = { 
    # this should happen inside the thread 
} 
x.start # i want to manually start the thread 

Zum zweiten:

x = MyThread.new 
x.my_attribute = some_value 
x.run = { 
    # this should happen when the thread runs 
} 
x.start 

Ich bin für etwas ähnliches wie diese suchen. Hoffe du kannst helfen.

+3

Warum können Sie "x.start" nicht einfach durch "x = Thread.new {etc}" ersetzen? –

Antwort

11

Frage 1

Untersuchung der MRT 1.8.7 Quelle ergab keine offensichtliche Möglichkeit, einen Faden in die "gestoppt" Zustand zu starten.

Sie können den Threadblock auf einem gesperrten Mutex blockieren und dann den Mutex entsperren, wenn der Thread ausgeführt werden soll.

#!/usr/bin/ruby1.8 

go = Mutex.new 
go.lock 
t = Thread.new do 
    puts "Thread waiting to go" 
    go.lock 
    puts "Thread going" 
end 
puts "Telling the thread to go" 
go.unlock 
puts "Waiting for the thread to complete" 
t.join 

# => Thread waiting to go 
# => Telling the thread to go 
# => Thread going 
# => Waiting for the thread to complete 

Frage 2 (Art)

Wussten Sie, Sie Argumente an deinen Thread passieren kann? Alles, was zu Thread.new geben wird als Block Argumente übergeben durch:

#!/usr/bin/ruby1.8 

t = Thread.new(1, 2, 3) do |a, b, c| 
    puts "Thread arguments: #{[a, b, c].inspect}" 
    # => Thread arguments: [1, 2, 3] 
end 

Es gibt auch „Thread lokale Variablen“ a pro Thread Schlüssel/Wert-Speicher. Verwenden Sie Thread#[]=, um Werte festzulegen, und Thread#[], um sie zurück zu erhalten. Sie können Zeichenfolgen oder Symbole als Schlüssel verwenden.

#!/usr/bin/ruby1.8 

go = Mutex.new 
go.lock 
t = Thread.new(1, 2, 3) do |a, b, c| 
    go.lock 
    p Thread.current[:foo] # => "Foo!" 
end 
t[:foo] = "Foo!" 
go.unlock 
t.join 

Frage 2, wirklich

können Sie tun, was Sie tun wollen. Es ist eine Menge Arbeit, vor allem wenn die übliche Handhabung von Threads so einfach ist. Hier finden Sie die plusses und Nachteile abwägen müssen:

#!/usr/bin/ruby1.8 

require 'forwardable' 

class MyThread 

    extend Forwardable 

    def_delegator :@thread, :join 
    def_delegator :@thread, :[]= 
    def_delegator :@thread, :[] 

    def initialize 
    @go = Mutex.new 
    @go.lock 
    @thread = Thread.new do 
     @go.lock 
     @stufftodo.call 
    end 
    end 

    def run(&block) 
    @stufftodo = block 
    @go.unlock 
    @thread.join 
    end 

end 

t = MyThread.new 
t[:foo] = "Foo!" 
t.run do 
    puts Thread.current[:foo] 
end 
t.join 

# => "Foo!" 
+0

Vielen Dank, dass Sie sich die Zeit genommen haben, diese detaillierte Antwort zu schreiben. Ich ging mit Thread-Variablen, mit der 'Thread.current' Methode. Deine Antwort war sehr interessant. Vielen Dank! – Geo

3
stuff_to_do = lambda do 
    # this happens in the thread 
end 

x = Thread.new(&stuff_to_do) 
+0

Wie erstelle ich den Thread, ohne ihn zu starten? – Geo

+0

Was macht das kaufmännische Und-Zeichen? Der Code bricht ohne es, aber ich möchte die Syntax verstehen. –

2

die example from Ruby-Doc 1.8.7 ignorieren, weil es eine Race-Bedingung enthält. Siehe Ruby 2 example, oder so etwas wie die folgenden:

Getestet habe ich diese in Ruby 2.0 und Ruby 1.8.7, und ich fand, dass #wakeup Aufruf in 1.8.7' nicht genug war, ich #run zu nennen hatte. Folgendes scheint in beiden zu funktionieren:

t = Thread.new { Thread.stop; puts "HELLO" } 
until t.stop?; end # ensure thread has actually stopped before we tell it to resume 
t.run 
+3

Dies hat eine Wettlaufsituation. Wenn der t.run vor dem Thread.stop stattfindet, wird der Thread nie darüber hinausgehen. – ChrisPhoenix

+0

Chris hat Recht. Ich bin gerade in diesen Zustand geraten. Ich habe den Post mit einem busy-Warte aktualisiert, um das Rennen zu vermeiden. – Patrick

Verwandte Themen