thread-pool.rb |
|
---|---|
Ruby Thread PoolA thread pool is useful when you wish to do some work in a thread, but do not know how much work you will be doing in advance. Spawning one thread for each task is potentially expensive, as threads are not free. In this case, it might be more beneficial to start a predefined set of threads and then hand off work to them as it becomes available. This is the pure essence of what a thread pool is: an array of threads, all just waiting to do some work for you! Prerequisites |
|
We need the Queue, as our thread pool is largely dependent on it. Thanks to this, the implementation becomes very simple! |
require 'thread' |
Public Interface |
|
|
class Pool |
initialization, or
|
def initialize(size) |
Before we do anything else, we need to store some information about
our pool. |
@size = size
@jobs = Queue.new
|
Creating our pool of threadsOnce preparation is done, it’s time to create our pool of threads. Each thread store its’ index in a thread-local variable, in case we need to know which thread a job is executing in later on. |
@pool = Array.new(@size) do |i|
Thread.new do
Thread.current[:id] = i |
We start off by defining a |
catch(:exit) do |
The worker thread life-cycle is very simple. We continuously wait
for tasks to be put into our job |
loop do |
Once we have a piece of work to be done, we will pull out the information we need and get to work. |
job, args = @jobs.pop
job.call(*args)
end
end
end
end
end
|
Work scheduling |
|
To schedule a piece of work to be done is to say to the |
def schedule(*args, &block) |
Your given task will not be run immediately; rather, it will be put
into the work |
@jobs << [block, args]
end
|
Graceful shutdown |
|
If you ever wish to close down your application, I took the liberty of making it easy for you to wait for any currently executing jobs to finish before you exit. |
def shutdown |
A graceful shutdown involves threads exiting cleanly themselves, and
since we’ve defined a |
@size.times do
schedule { throw :exit }
end
|
And now one final thing: wait for our |
@pool.map(&:join)
end
end |
DemonstrationRunning this file will display how the thread pool works. |
if $0 == __FILE__ |
|
p = Pool.new(10)
|
|
20.times do |i|
p.schedule do
sleep rand(4) + 2
puts "Job #{i} finished by thread #{Thread.current[:id]}"
end
end |
|
at_exit { p.shutdown }
end |
License (X11 License)Copyright © 2012, Kim Burgestrand [email protected] Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the “Software”), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. |
|