Поиск…


Семантика основной темы

Новый поток, отдельный от выполнения основного потока, может быть создан с помощью Thread.new .

thr = Thread.new {
  sleep 1 # 1 second sleep of sub thread
  puts "Whats the big deal"
}

Это автоматически запустит выполнение нового потока.

Чтобы заморозить выполнение основного потока, пока новый поток не остановится, используйте join :

thr.join #=> ... "Whats the big deal"

Обратите внимание, что Thread, возможно, уже был завершен, когда вы вызываете join, и в этом случае выполнение будет продолжаться в обычном режиме. Если подпоток никогда не соединяется, а основной поток завершается, подпоток не будет выполнять какой-либо оставшийся код.

Доступ к общим ресурсам

Используйте мьютекс для синхронизации доступа к переменной, к которой обращаются из нескольких потоков:

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

В противном случае значение counter видимого в данный момент одному потоку, может быть изменено другим потоком.

Пример без Mutex (см., Например, Thread 0 , где Before и After отличаются более чем на 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

Пример с 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

Как убить нить

Вы вызываете использование Thread.kill или Thread.terminate :

thr = Thread.new { ... }
Thread.kill(thr)

Завершение темы

Поток заканчивается, если он достигает конца своего кодового блока. Лучший способ прервать поток на раннем этапе - убедить его достичь конца своего кодового блока. Таким образом, поток может запускать код очистки перед смертью.

Этот поток запускает цикл, пока переменная экземпляра continue имеет значение true. Установите эту переменную в значение false, и нить умрет естественной смертью:

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


Modified text is an extract of the original Stack Overflow Documentation
Лицензировано согласно CC BY-SA 3.0
Не связан с Stack Overflow