Существует класс Queue
в thread
в стандартной библиотеке.Используя это, вы можете сделать что-то вроде этого:
require 'thread'
queue = Queue.new
threads = []
# add work to the queue
queue << work_unit
4.times do
threads << Thread.new do
# loop until there are no more things to do
until queue.empty?
# pop with the non-blocking flag set, this raises
# an exception if the queue is empty, in which case
# work_unit will be set to nil
work_unit = queue.pop(true) rescue nil
if work_unit
# do work
end
end
# when there is no more work, the thread will stop
end
end
# wait until all threads have completed processing
threads.each { |t| t.join }
Причина, по которой я всплываю с неблокирующим флагом, заключается в том, что между until queue.empty?
и всплывающим элементом другой поток мог выдвинуть очередь, поэтому, если толькоустановлен флаг неблокирования, мы могли бы застрять в этой строке навсегда.
Если вы используете MRI, интерпретатор Ruby по умолчанию, имейте в виду, что потоки не будут абсолютно параллельными.Если ваша работа связана с процессором, вы можете запустить однопоточный.Если у вас есть какая-то операция, которая блокирует IO, вы можете получить некоторый параллелизм, но YMMV.Кроме того, вы можете использовать интерпретатор, который обеспечивает полный параллелизм, такой как jRuby или Rubinius.