Reputation: 12378
Running this
# in initialize
@queue = Queue.new
@threads = Array.new(NUM_THREADS) do
Thread.new do
until @queue.empty?
puts @queue.shift
end
end
end
# later in another method, calling
@threads.each { |t| puts t.alive? } # puts false
@queue.push('something else')
# new item is not processed by thread
How do I keep a Ruby thread alive so it can keep accepting stuff from a queue?
Upvotes: 2
Views: 1059
Reputation: 1504
You probably want to use Queue from Ruby core library.
Methods pop
, deq
and shift
can be used to retrieve data from the queue.
With these methods, according to the documentation
If the queue is empty, the calling thread is suspended until data is pushed onto the queue.
With Queue
, your code snippet would look like so
@queue = Queue.new
@threads = Array.new(NUM_THREADS) do
Thread.new do
while (item = @queue.shift)
puts item
end
end
end
# later in another method
@threads.each { |t| puts t.alive? } # true
@queue.push('something else') # is printed out
Queue#shift
keeps the thread waiting, until something is pushed into the queue. You still need the loop, so that after handling the item, the thread will stay alive, suspended, waiting for the next item.
Upvotes: 0
Reputation: 26758
The issue is you initialize the threads before adding anything to the queue. The threads start and die before the @queue.push
line is run.
If you want to keep alive the thread even if there is nothing in the queue, you can change the logic of the thread so it loops forever:
Thread.new do
loop do
if val = @queue.shift
puts val
end
end
end
You could decrease the CPU consumption by putting a sleep
call inside the thread's loop, say it sleeps 0.1 seconds each iteration and thus it could process a max of 10 items per second. For example running the following in my Ruby REPL raises the process' CPU consumption from around 0 to 25% (which is undesirably high)
100.times { Thread.new { loop { } } }
But the following uses less than 1%:
100.times { Thread.new { loop { sleep 0.1 } } }
There are other ways to manage CPU consumption of background processes other than putting arbitrary sleep
numbers in there: for example eventmachine, resque, or sidekiq.
Upvotes: 1