ワーカースレッドの停止

久々の「増補改訂版 Java言語で学ぶデザインパターン入門 マルチスレッド編」を Ruby で読むシリーズです。第 8 章 Worker Thread の問題 8-6 (ワーカースレッドの停止)を書いてみました。
Java の Thread インターフェースに似た動作をさせるために NameThread モジュールをつくり、スレッドの名前とスレッド・オブジェクトの生成(start)と停止(kill)をおこなうようにしました。
問題は、Ruby で例外を使ってスレッドを直接 kill せずに例外で安全に停止させる方法を私が理解できていないこと。わかったところで、良い回答を立てたいと思います。
ワーカースレッドの停止 (良い回答)

# 悪い回答:安全でない stop_thread 版

require 'thread.rb'

class Request
  def initialize(name, no) @name, @no = name.dup.freeze, no end
  def execute()
    puts "#{Thread.current[:name]} executes #{self}"
    sleep rand(1000).to_f / 1000.0
  end
  def to_s() "[ Request from #{@name} No. #{@no} ]" end
end

module NameThread
  def initialize(name)
    @name = name
    @thread = nil
  end
  def start()
    @thread = Thread.start(@name) {|thname|
      Thread.current[:name] = thname
      run
    }
  end
  def stop_thread() @thread.kill end
end

class ClientThread
  include NameThread
  def initialize(name, channel)
    super(name)
    @channel = channel
  end
  def run()
    i = 0
    while true
      @channel.put_request(Request.new(Thread.current[:name], i))
      sleep rand(1000).to_f / 1000.0
      i += 1
    end
  end
end

class WorkerThread
  include NameThread
  def initialize(name, channel)
    super(name)
    @channel = channel
  end
  def run()
    while true
      @channel.take_request.execute
    end
  end
end

class Channel
  MAX_REQUEST = 100
  def initialize(nthread)
    @nthread = nthread
    @threads = []
    @requestQueue = SizedQueue.new(MAX_REQUEST)
  end
  def start_workers()
    @nthread.times {|i|
      th = WorkerThread.new("Worker-#{i}", self)
      @threads.push th
      th.start
    }
  end
  def stop_workers()
    @threads.each {|th| th.stop_thread }
  end
  def put_request(r) @requestQueue.push(r) end
  def take_request() @requestQueue.pop end
end

channel = Channel.new(5)
channel.start_workers
alice = ClientThread.new('Alice', channel)
bobby = ClientThread.new('Bobby', channel)
chris = ClientThread.new('Chris', channel)
alice.start
bobby.start
chris.start
sleep 5
alice.stop_thread
bobby.stop_thread
chris.stop_thread
channel.stop_workers