Latest web development tutorials

Ruby-Multithreading

Jedes Programm auf dem System ausgeführt ist ein Prozess. Jeder Prozeß enthält ein oder mehrere Threads.

Ein Thread ist ein einzelner sequentieller Programmablaufsteuerung, gleichzeitig mehrere Threads in einem einzigen Programm verschiedene Dinge tun, die so genannte Multi-Threading laufen.

Rubin, können wir von mehreren Threads Thread-Klasse erstellt werden, sind Ruby-Threads ein leichtes, kann es eine effiziente Möglichkeit, parallel Code zu implementieren.


Erstellen eines Ruby-Thread

Um einen neuen Thread starten, können Sie einfach Thread.new nennen:

# 线程 #1 代码部分
Thread.new {
  # 线程 #2 执行代码
}
# 线程 #1 执行代码

Beispiele

Das folgende Beispiel zeigt, wie Multithreading zu verwenden, in Ruby-Programm:

#!/usr/bin/ruby

def func1
   i=0
   while i<=2
      puts "func1 at: #{Time.now}"
      sleep(2)
      i=i+1
   end
end

def func2
   j=0
   while j<=2
      puts "func2 at: #{Time.now}"
      sleep(1)
      j=j+1
   end
end

puts "Started At #{Time.now}"
t1=Thread.new{func1()}
t2=Thread.new{func2()}
t1.join
t2.join
puts "End at #{Time.now}"

Der obige Code wird als Ergebnis der Ausführung:

Started At Wed May 14 08:21:54 -0700 2014
func1 at: Wed May 14 08:21:54 -0700 2014
func2 at: Wed May 14 08:21:54 -0700 2014
func2 at: Wed May 14 08:21:55 -0700 2014
func1 at: Wed May 14 08:21:56 -0700 2014
func2 at: Wed May 14 08:21:56 -0700 2014
func1 at: Wed May 14 08:21:58 -0700 2014
End at Wed May 14 08:22:00 -0700 2014

Thema Life Cycle

1, einen Thread erstellen Thread.new verwenden, können Sie auch die gleiche Syntax Thread.start oder Thread.fork verwenden drei Möglichkeiten, um einen Thread zu erstellen.

2, einen Thread zu erstellen, ohne starten, dann wird der Faden automatisch ausgeführt werden.

3, Thread-Klasse definiert Methoden Thread zu manipulieren. Thread der Ausführung Thread.new Codeblöcke.

4 ist der Gewindesatz ist der Wert der letzten Anweisung in dem Gewinde kann der Faden durch ein Verfahren aufgerufen werden, wenn der Thread beendet ist, wird der Wert des Fadens zurückkehrt oder zurückzukehren keinen Wert, bis der Thread beendet ist.

5, kehrt Thread.current Methode ein Objekt für den aktuellen Thread-Darstellung. Thread.main Methode gibt den Haupt-Thread.

6, wobei das Verfahren durch Thread.Join Threads ausgeführt wird, wird diese Methode unterbrechen wird, um den Haupt-Thread, bis der aktuelle Thread beendet.


Thread-Zustand

Thema hat fünf Staaten:

Thread-Zustand Rückgabewert
ausführbar Lauf
schlafend schlafend
verlassen Abbruchs
Normale Beendigung falsch
Abnormale Beendigung auftritt Null

Themen und anomale

Wenn ein Thread Ausnahme auftritt, und keine Rettung gefangen genommen wurde, würde der Faden normalerweise ohne Vorwarnung beendet werden. Allerdings, wenn andere Threads Thread # beitreten, weil die Beziehung für diesen Thread gewartet hat, dann werden die wartenden Threads wird auch die gleiche Ausnahme ausgelöst werden.

begin
  t = Thread.new do
    Thread.pass    # 主线程确实在等join
    raise "unhandled exception"
  end
  t.join
rescue
  p $!  # => "unhandled exception"
end

Verwenden Sie die folgenden drei Methoden können Sie den Interpreter erhalten, um den Betrieb zu unterbrechen, wenn ein Thread auf eine Ausnahme aufgrund beendet.

  • Startup - Skript gibt Option-d und Debugging - Modus - Betrieb.
  • Mit Thread.abort_on_exception das Kennzeichen.
  • Verwenden Sie Thread#abort_on_exception angegebenen Thread - Set - Flag.

Wenn eines von drei Verfahren unter Verwendung der oben beschriebenen, wird das gesamte Interpreter abgebrochen werden.

t = Thread.new { ... }
t.abort_on_exception = true

Themen-Synchronisation

In Ruby bietet drei aufeinander abgestimmten Weise, nämlich:

1. Mutex-Klasse implementiert Threadsynchronisierung

2. Regulatorische Datenübertragung Queue-Klasse implementieren Thread-Synchronisation

3. Verwenden Sie Conditionsynchronisationssteuerung

Durch Mutex implementiert Klasse Thread-Synchronisation

Durch die Mutex-Klasse implementiert die Thread-Synchronisation Kontrolle, wenn Sie auch eine Programmvariable Uhr in mehreren Threads benötigen, können Sie die Sperre zu verwenden den variablen Teil zu sperren. Code ist wie folgt:

#!/usr/bin/ruby

require "thread"
puts "Synchronize Thread"

@num=200
@mutex=Mutex.new

def buyTicket(num)
     @mutex.lock
          if @num>=num
               @num=@num-num
               puts "you have successfully bought #{num} tickets"
          else
               puts "sorry,no enough tickets"
          end
     @mutex.unlock
end

ticket1=Thread.new 10 do
     10.times do |value|
     ticketNum=15
     buyTicket(ticketNum)
     sleep 0.01
     end
end

ticket2=Thread.new 10 do
     10.times do |value|
     ticketNum=20
     buyTicket(ticketNum)
     sleep 0.01
     end
end

sleep 1
ticket1.join
ticket2.join

Der obige Code wird als Ergebnis der Ausführung:

Synchronize Thread
you have successfully bought 15 tickets
you have successfully bought 20 tickets
you have successfully bought 15 tickets
you have successfully bought 20 tickets
you have successfully bought 15 tickets
you have successfully bought 20 tickets
you have successfully bought 15 tickets
you have successfully bought 20 tickets
you have successfully bought 15 tickets
you have successfully bought 20 tickets
you have successfully bought 15 tickets
sorry,no enough tickets
sorry,no enough tickets
sorry,no enough tickets
sorry,no enough tickets
sorry,no enough tickets
sorry,no enough tickets
sorry,no enough tickets
sorry,no enough tickets
sorry,no enough tickets

Neben der Verwendung von Schloss verriegelt Variablen können Sie auch try_lock verriegelte Variable verwenden, können Sie auch Mutex.synchronize Zugriff auf eine bestimmte Variable synchronisieren.

Regulatorische Datenübertragung der Queue-Klasse implementiert Threadsynchronisierung

Queue-Klasse, die einen Thread Support-Warteschlange darstellt, kann die Warteschlange bis zum Ende des Besuchs synchronisiert werden. Verschiedene Threads können eine einheitliche Klasse zu verwenden, aber keine Sorge darüber, ob die Daten in dieser Warteschlange synchronisiert werden, zusätzlich die Verwendung von SizedQueue Klasse Warteschlangenlänge zu begrenzen,

SizedQueue Klasse kann sehr praktisch sein, um uns Threaded-Anwendungen entwickeln helfen zu synchronisieren, sollten Synchronisationsprobleme zu der langen Warteschlange hinzugefügt werden, Sie kümmern sich nicht um Threads.

Klassische Produzenten und Konsumenten:

#!/usr/bin/ruby

require "thread"
puts "SizedQuee Test"

queue = Queue.new

producer = Thread.new do
     10.times do |i|
          sleep rand(i) # 让线程睡眠一段时间
          queue << i
          puts "#{i} produced"
     end
end

consumer = Thread.new do
     10.times do |i|
          value = queue.pop
          sleep rand(i/2)
          puts "consumed #{value}"
     end
end

consumer.join

Programmausgabe:

SizedQuee Test
0 produced
1 produced
consumed 0
2 produced
consumed 1
consumed 2
3 produced
consumed 34 produced

consumed 4
5 produced
consumed 5
6 produced
consumed 6
7 produced
consumed 7
8 produced
9 produced
consumed 8
consumed 9

Thread-Variablen

Thread kann seine private Variable, einen Thread private Variable Schreib Thread, wenn der Thread erstellt wird. Es kann im Rahmen des Gewindes verwendet werden, aber der Faden kann nicht extern geteilt werden.

Aber manchmal sind die lokalen Thread-Variablen brauchen keinen neuen Thread oder den Haupt-Thread zuzugreifen, wie zu tun? Rubin ermöglicht es ihnen, einen Thread zu erstellen, indem Sie den Variablennamen zur Verfügung gestellt wird, wird der Faden ähnlichen Stil Hash-Hash-Tabelle zu sehen, wie. Mit dem [] = geschrieben von [] Daten lesen. Wir schauen auf den folgenden Code:

#!/usr/bin/ruby

count = 0
arr = []

10.times do |i|
   arr[i] = Thread.new {
      sleep(rand(0)/10.0)
      Thread.current["mycount"] = count
      count += 1
   }
end

arr.each {|t| t.join; print t["mycount"], ", " }
puts "count = #{count}"

Der obige Code ausgeführt wird, ausgegeben wird:

8, 0, 3, 7, 2, 1, 6, 5, 4, 9, count = 10

Die Haupt-Thread wartet auf das Kind Thread-Ausführung ist, abgeschlossen und gibt dann jeden Wert. .


Thread-Priorität

Thema Priorität ist der wesentliche Faktor der Thread-Scheduling. Andere Faktoren umfassen die Länge der Zeit, CPU-thread Paket-Scheduling durchzuführen, und so weiter.

Sie können Thread.Priority verwenden, um ein Thread Priorität erhalten und verwenden Thread.Priority = Methode, um die Thread-Priorität einzustellen.

Eine Priorität des Threads automatisch auf 0. Schnellere Ausführung mit höherer Priorität.

Ein Thread kann auf alle Daten zugreifen im Rahmen der eigenen, aber wenn es andere Threads Daten in einem Thread zugreifen müssen sein sollte, wie es zu tun? Thread-Klasse bietet Thread-Daten aufeinander zugreifen, können Sie einfach einen Thread als Hash-Tabelle setzen kann, kann in alle gängigen Gewinde [] = Write-Daten verwendet werden, verwenden Sie [] Lesen von Daten.

athr = Thread.new { Thread.current["name"] = "Thread A"; Thread.stop }
bthr = Thread.new { Thread.current["name"] = "Thread B"; Thread.stop }
cthr = Thread.new { Thread.current["name"] = "Thread C"; Thread.stop }
Thread.list.each {|x| puts "#{x.inspect}: #{x["name"]}" }

Wir können sehen, den Faden als Hash-Tabelle, verwenden Sie [] und [] = Methode erzielten wir Daten zwischen Threads zu teilen.


Thema Mutex

Mutex (Mutal Exclusion = mutex) ist ein Verfahren zur Multi-Threaded-Programmierung, ein Mechanismus zwei Threads für die gleichen öffentlichen Ressourcen (wie globale Variablen) lesen und schreiben gleichzeitig zu verhindern.

Beispiele für nicht-use MUTAX

#!/usr/bin/ruby
require 'thread'

count1 = count2 = 0
difference = 0
counter = Thread.new do
   loop do
      count1 += 1
      count2 += 1
   end
end
spy = Thread.new do
   loop do
      difference += (count1 - count2).abs
   end
end
sleep 1
puts "count1 :  #{count1}"
puts "count2 :  #{count2}"
puts "difference : #{difference}"

Führen Sie das obige Beispiel Ausgabe lautet:

count1 :  9712487
count2 :  12501239
difference : 0

Beispiel für MUTAX

#!/usr/bin/ruby
require 'thread'
mutex = Mutex.new

count1 = count2 = 0
difference = 0
counter = Thread.new do
   loop do
      mutex.synchronize do
         count1 += 1
         count2 += 1
      end
    end
end
spy = Thread.new do
   loop do
       mutex.synchronize do
          difference += (count1 - count2).abs
       end
   end
end
sleep 1
mutex.lock
puts "count1 :  #{count1}"
puts "count2 :  #{count2}"
puts "difference : #{difference}"

Führen Sie das obige Beispiel Ausgabe lautet:

count1 :  1336406
count2 :  1336406
difference : 0

Deadlock

Mehr als zwei Betriebseinheiten sind beide Seiten warten auf die andere laufen zu stoppen, die Systemressourcen zu erhalten, aber nicht eine Partei ein vorzeitiges Ausscheiden, diese Situation wird Deadlock genannt.

Zum Beispiel kann ein Prozess p1 Display einnimmt, während Sie den Drucker verwenden müssen, und der Drucker durch den Prozess p2 belegt ist, p2 muss auch den Monitor verwenden, wodurch eine Sackgasse bilden.

Wenn wir Mutex braucht Aufmerksamkeit Thread-Deadlock-Objekt verwenden.

Beispiele

#!/usr/bin/ruby
require 'thread'
mutex = Mutex.new

cv = ConditionVariable.new
a = Thread.new {
   mutex.synchronize {
      puts "A: I have critical section, but will wait for cv"
      cv.wait(mutex)
      puts "A: I have critical section again! I rule!"
   }
}

puts "(Later, back at the ranch...)"

b = Thread.new {
   mutex.synchronize {
      puts "B: Now I am critical, but am done with cv"
      cv.signal
      puts "B: I am still critical, finishing up"
   }
}
a.join
b.join

Das obige Beispiel Ausgabe lautet:

A: I have critical section, but will wait for cv
(Later, back at the ranch...)
B: Now I am critical, but am done with cv
B: I am still critical, finishing up
A: I have critical section again! I rule!

Thread-Klasse-Methode

Vollständige Thread (Thread) Klassenmethode wie folgt:

Nein. Methode Beschreibung
1 Thread.abort_on_exception
Wenn es wahr ist, wenn ein Thread aufgrund einer Ausnahme beendet wird, wird der gesamte Dolmetscher unterbrochen. Der Standardwert ist falsch, das heißt, unter normalen Umständen, wenn ein Thread Ausnahme auftritt und die Ausnahme nicht Thread # join und andere erkannt, wird der Faden ohne Warnung beendet werden.
2 Thread.abort_on_exception =
Wenn auftrue gesetzt,einmal beendet ein Thread aufgrund einer Ausnahme, wird der gesamte Dolmetscher unterbrochen werden. Gibt neuen Staat
3 Thread.critical
Gibt einen Booleschen Wert.
4 Thread.critical =
Wenn der Wert true ist, wird der Faden umgeschaltet werden. Wenn der aktuelle Thread (Stopp) oder ein Signal (Signal) Intervention zu hängen, wird sein Wert automatisch auf false geändert werden.
5 Thread.current
Gibt den aktuellen laufenden Faden (der aktuelle Thread).
6 Thread.exit
Er beendet den aktuellen Thread. Gibt den aktuellen Thread. Wenn der aktuelle Thread der einzige Thread, den Ausgang mit (0) seinen Betrieb zu beenden.
7 Thread.fork {block}
Wie bei Thread.new erzeugen Fäden.
8 Thread.kill (einThread)
Beenden Sie den Faden läuft.
9 Thread.list
Liefert ein Array von Live-Thread ausgeführt oder angehalten.
10 Thread.main
Zurück zur Haupt-Thread.
11 Thread.new ([arg] *) { | args | block}
Generieren Faden und beginnen Ausführung. Die Zahl wird intakt an den Block übergeben werden. Dieser einen Thread zur gleichen Zeit gestartet werden kann, wird der Wert der lokalen Variablen, die mit der Thread übergeben werden.
12 Thread.pass
Die rechte anderen Threads ausgeführt werden. Es ist nicht der Zustand der laufenden Threads ändert, aber die Kontrolle über andere Threads übergeben kann (Explicit Thread-Scheduling) ausgeführt werden.
13 Thread.start ([args] *) { | args | block}
Generieren Faden und beginnen Ausführung. Die Zahl wird intakt an den Block übergeben werden. Dieser einen Thread zur gleichen Zeit gestartet werden kann, wird der Wert der lokalen Variablen, die mit der Thread übergeben werden.
14 Thread.stop
Der aktuelle Thread unterbrochen, bis die anderen Threads laufen Verfahren den Faden wieder aufwachen.

Themen-Instanz-Methode

Das folgende Beispiel ruft der Thread-Instanz Verfahren beitreten:

#!/usr/bin/ruby

thr = Thread.new do   # 实例化
   puts "In second thread"
   raise "Raise exception"
end
thr.join   # 调用实例化方法 join

Dies ist die komplette Liste der Beispiele des Verfahrens:

Nein. Methode Beschreibung
1 thr [name]
Entfernen Sie den Faden des Namens der inhärenten Daten entsprechen. Name kann eine Zeichenfolge oder ein Symbol sein. Wenn der Name auf die Daten nicht entspricht, kehrt sie gleich Null.
2 thr [name] =
Stellen Sie den Thread-Namen-Wert in den entsprechenden Kenndaten können Name einen String oder ein Symbol sein. Wenn auf Null setzen, entfernt in diesem Thread die entsprechenden Daten.
3 thr.abort_on_exception
Gibt einen Booleschen Wert.
4 thr.abort_on_exception =
Wenn der Wert wahr ist, dann, wenn ein Thread beendet aufgrund einer Ausnahme, wird der gesamte Dolmetscher unterbrochen werden.
5 thr.alive?
Wenn der Thread "live" ist, gibt es wahr.
6 thr.exit
Beenden Sie den Faden läuft. Kosten selbst.
7 thr.join
Unterbricht den aktuellen Thread, bis die Selbst laufen, bis der Thread beendet wird. Wenn der Selbst aufgrund abnormaler Beendigung der aktuelle Thread die gleiche Ausnahme auslösen.
8 thr.key?
Wenn der Name der inhärenten Daten entsprechend definierten Fäden gegeben hat, dann gibt true zurück
9 thr.kill
ÄhnlicheThread.exit.
10 thr.priority
Gibt die Priorität des Threads. Die Standardpriorität 0. Je höher der Wert ist, desto höher ist die Priorität.
11 thr.priority =
Einstellen der Thread-Priorität. Sie können sie auch auf negativ gesetzt.
12 thr.raise (anException)
Innerhalb dieser Faden gewaltsam geworfen.
13 thr.run
Starten Sie Pending (Stopp) Faden. Der Unterschied besteht darin, dass mit dem Wake-up-Thread-Umschalt sofort durchführen wird. Wenn mit dieser Methode die Toten zu verarbeiten ThreadError Ausnahme ausgelöst werden.
14 thr.safe_level
Gibt Selbstsicherheitsstufe. Safe_level den aktuellen Thread $ SAFE gleich.
15 thr.status
Unter Verwendung der Zeichenfolge "run", "Schlaf" oder "Abbrechen", um den Status der Live-Thread, um anzuzeigen, wenn ein Thread normal beendet wird, dann wird false zurückgegeben. Ruoyin abnormalen Beendigung, dann gibt es gleich Null.
16 thr.stop?
Wenn der Faden Zustand (tot) beendet oder aussetzen (Stopp), die Rückkehr wahr.
17 thr.value
Warten, bis der Selbst Thread beendet (äquivalent zu verbinden), um den Wert des Blocks des Threads zurück, wenn die laufenden Threads während abnormal auftreten, wird die Ausnahme wieder angehoben werden.
18 thr.wakeup
Der Staat wird unterbrochen (Stop) Faden in den Bereitschaftszustand (run), wenn die Methode auf dem toten Thread ausgeführt wird, wird ThreadError Ausnahme ausgelöst.