This page contains automated test results for code from O'Reilly's Ruby Cookbook. If this code looks interesting or useful, you might want to buy the whole book.
Limiting Multithreading with a Thread Pool | ||
---|---|---|
Code | Expected | Actual |
require 'thread' class ThreadPool def initialize(max_size) @pool = [] @max_size = max_size @pool_mutex = Mutex.new @pool_cv = ConditionVariable.new end def dispatch(*args) Thread.new do # Wait for space in the pool. @pool_mutex.synchronize do while @pool.size >= @max_size print "Pool is full; waiting to run #{args.join(',')}...\n" if $DEBUG # Sleep until some other thread calls @pool_cv.signal. @pool_cv.wait(@pool_mutex) end end @pool << Thread.current begin yield(*args) rescue => e exception(self, e, *args) ensure @pool_mutex.synchronize do # Remove the thread from the pool. @pool.delete(Thread.current) # Signal the next waiting thread that there's a space in the pool. @pool_cv.signal end end end end def shutdown @pool_mutex.synchronize { @pool_cv.wait(@pool_mutex) until @pool.empty? } end def exception(thread, exception, *original_args) # Subclass this method to handle an exception within a thread. puts "Exception in thread #{thread}: #{exception}" end end $DEBUG = true pool = ThreadPool.new(3) 1.upto(5) do |i| pool.dispatch(i) do |i| print "Job #{i} started.\n" sleep(5-i) print "Job #{i} complete.\n" end end |
Job 1 started. Job 3 started. Job 2 started. Pool is full; waiting to run 4... Pool is full; waiting to run 5... Job 3 complete. Job 4 started. Job 2 complete. Job 5 started. Job 5 complete. Job 4 complete. Job 1 complete. |
Job 1 started. Job 2 started. Job 3 started. Pool is full; waiting to run 4... Pool is full; waiting to run 5... |
pool.shutdown |
nil |