Jest Queue
klasa w thread
w bibliotece standardowej. Korzystanie że można zrobić coś takiego:
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 }
Powodem pop z flagą non-blocking, że pomiędzy until queue.empty?
i pop inny wątek mógł pop'ed kolejkę, więc chyba bez blokowania flaga jest ustawiona, możemy na zawsze utknąć w tej linii.
Jeśli używasz MRI, domyślnego interpretera Ruby, pamiętaj, że wątki nie będą absolutnie współbieżne. Jeśli twoja praca jest związana z procesorem, możesz równie dobrze uruchomić pojedynczy wątek. Jeśli masz operację, która blokuje IO, możesz uzyskać paralelizm, ale YMMV. Alternatywnie możesz użyć interpretera, który pozwala na pełną współbieżność, na przykład jRuby lub Rubinius.
W oskard, to sugeruje, że na 4 ': END_OF_WORK'' work_unit's zamiast nieblokujące POP. Ostatnie oświadczenie o wątkach, które nie mają jednocześnie uruchomionych procesorów, odnosi się do YARV, ale nie do JRuby. –
@AndrewGrimm, podoba mi się ta odpowiedź, ponieważ czasami chcesz mieć kolejkę roboczą i wątki wokół, aby pracować, gdy dodawany jest nowy element pracy. – akostadinov