Another useful data structure is Queue. This is a synchronised, i.e. thread safe, first-in first-out queue. This makes it easy to coordinate work between threads.
Below is a simple example of a program that lets you enter multiple URLs to download, then works through them one by one in the background:
require "thread" # Queue is part of the thread library
require "net/http"
to_do = Queue.new
Thread.abort_on_exception = true # if one thread dies, everyone dies
interface = Thread.new do
loop do
url = STDIN.gets # waits here until a URL has been entered
if url && url != "quit\n"
to_do.push(URI.parse(url))
else
to_do.push(false)
break
end
end
end
fetcher = Thread.new do
loop do
uri = to_do.pop # waits until there's a URI in the queue
break unless uri
result = Net::HTTP.get(uri)
File.open("#{uri.host}#{uri.path.tr("/", ":")}", "w+") do |f|
f << result
end
puts "downloaded #{uri}"
end
end
[interface, fetcher].each(&:join) # don't exit until the threads are done