Ruby Language
Wątek
Szukaj…
Podstawowa semantyka wątków
Nowy wątek, niezależny od wykonywania głównego wątku, można utworzyć za pomocą Thread.new
.
thr = Thread.new {
sleep 1 # 1 second sleep of sub thread
puts "Whats the big deal"
}
Spowoduje to automatyczne rozpoczęcie wykonywania nowego wątku.
Aby zatrzymać wykonywanie głównego wątku, dopóki nowy wątek się nie zatrzyma, użyj polecenia join
:
thr.join #=> ... "Whats the big deal"
Zwróć uwagę, że wątek mógł już zostać zakończony po wywołaniu funkcji join, w takim przypadku wykonanie będzie kontynuowane normalnie. Jeśli wątek podrzędny nigdy nie zostanie przyłączony, a wątek główny zostanie ukończony, wątek podrzędny nie wykona żadnego pozostałego kodu.
Dostęp do udostępnionych zasobów
Użyj muteksu, aby zsynchronizować dostęp do zmiennej dostępnej z wielu wątków:
counter = 0
counter_mutex = Mutex.new
# Start three parallel threads and increment counter
3.times.map do |index|
Thread.new do
counter_mutex.synchronize { counter += 1 }
end
end.each(&:join) # Wait for all threads to finish before killing the process
W przeciwnym razie wartość counter
widocznego obecnie dla jednego wątku może zostać zmieniona przez inny wątek.
Przykład bez Mutex
(patrz np. Thread 0
, gdzie Before
i After
różnią się o więcej niż 1
):
2.2.0 :224 > counter = 0; 3.times.map { |i| Thread.new { puts "[Thread #{i}] Before: #{counter}"; counter += 1; puts "[Thread #{i}] After: #{counter}"; } }.each(&:join)
[Thread 2] Before: 0
[Thread 0] Before: 0
[Thread 0] After: 2
[Thread 1] Before: 0
[Thread 1] After: 3
[Thread 2] After: 1
Przykład z Mutex
:
2.2.0 :226 > mutex = Mutex.new; counter = 0; 3.times.map { |i| Thread.new { mutex.synchronize { puts "[Thread #{i}] Before: #{counter}"; counter += 1; puts "[Thread #{i}] After: #{counter}"; } } }.each(&:join)
[Thread 2] Before: 0
[Thread 2] After: 1
[Thread 1] Before: 1
[Thread 1] After: 2
[Thread 0] Before: 2
[Thread 0] After: 3
Jak zabić wątek
Thread.kill
use Thread.kill
lub Thread.terminate
:
thr = Thread.new { ... }
Thread.kill(thr)
Zakończenie wątku
Wątek kończy się, jeśli osiągnie koniec swojego bloku kodu. Najlepszym sposobem wcześniejszego zakończenia wątku jest przekonanie go, aby osiągnął koniec bloku kodu. W ten sposób wątek może uruchomić kod czyszczenia przed śmiercią.
Wątek uruchamia pętlę, podczas gdy zmienna instancji ciąg dalszy jest prawdziwa. Ustaw tę zmienną na false, a nić umrze śmiercią naturalną:
require 'thread'
class CounterThread < Thread
def initialize
@count = 0
@continue = true
super do
@count += 1 while @continue
puts "I counted up to #{@count} before I was cruelly stopped."
end
end
def stop
@continue = false
end
end
counter = CounterThread.new
sleep 2
counter.stop