Two-Phase Termination(interrupt版) →失敗
javaにおけるThread#interruptのような「wait/sleep状態のスレッドを中断させるメソッド」というものが分からなかったので、その点を省略しています。
http://d.hatena.ne.jp/qnzm/20080209/1202524095
と言っていたのですが、単純に例外投げるようThread拡張すればいいような気がしてきました。
Object クラスの wait()、wait(long)、wait(long, int) メソッドの呼び出し、またはこのクラスの join(), join(long)、join(long, int)、sleep(long)、または sleep(long, int) メソッドの呼び出しでこのスレッドがブロックされる場合、割り込みステータスはクリアされ、InterruptedException を受け取ります。
Thread (Java 2 プラットフォーム SE v1.4.0)
Javaでも、interrupt呼び出されたらその場でInterruptedExceptionが発生するわけですし。
その前提で、前のソースを一部調整してみました。
require 'thread' require 'monitor' class Thread def interrupt raise Interrupt end end class Logger include MonitorMixin def initialize @t = nil @started = false @finished = false super() end def start synchronize do return if @started || @finished log = "out.log" File.delete(log) if File.exists?(log) @t = Thread.start do until @finished do File.open(log, 'a') do |w| begin w.puts "<<#{Time.now}>>" for i in 1..9 do w.print rand(i) end w.print "\n" sleep(1) #重い処理 w.puts "--------------" rescue Interrupt @finished = true ensure next end end end puts "<<Exit Thread>>" end @started = true end end def interrupt @t.interrupt end def stop return unless @started return if @finished self.interrupt end end l = Logger.new l.start sleep(3) l.stop
(追記:2008/02/19)
コメントでpanさんが指摘されているように、上のエントリはThread#interruptを勘違いしてます。
Therad#interruptは
- 実行中 → スレッドをインタラプト状態にする
- sleep or wait → InterruptedExceptionをthrow
と動作するべきで、上のように呼ばれたら常に例外投げればいいというものではありませんでした。
interrupt呼出時の動作を表にするとこんな感じですかね。(縦が状態、横が振る舞い)
実行中 | sleep or wait | |
---|---|---|
割込フラグをtrueに | ○ | × |
InterruptedException発生 | × | ○ |