読者です 読者をやめる 読者になる 読者になる
無料で使えるシステムトレードフレームワーク「Jiji」 をリリースしました!

・OANDA Trade APIを利用した、オープンソースのシステムトレードフレームワークです。
・自分だけの取引アルゴリズムで、誰でも、いますぐ、かんたんに、自動取引を開始できます。

FileChannel#lock中の割り込み

FileChannel#lock()を実行し、ロックの取得を待っているスレッドに割り込むと、「FileLockInterruptionExceptionが発生する」とか書いてある(ように読める)んだけど、何も起きない・・・。

// ロックするファイル
final File file = new File( "./test.tmp" );

// ファイルを開いてロックする
class Lock implements Closeable {

    FileOutputStream out = null;
    FileChannel channel = null;
    FileLock lock = null;
    
    Lock( File file ) throws IOException {
        try {
            // OutputStreamを作成
            out = new FileOutputStream( file );
            // FileChannelを開く
            channel =  out.getChannel();
            // 排他ロック
            lock = channel.lock(0, Long.MAX_VALUE, false);
        } catch ( IOException e ) {
            close();
            throw e;
        } catch ( RuntimeException e ) {
            close();
            throw e;
        }
    }
    
    public void close() throws IOException {
        try {
            try {
                // ロックを開放
                if ( lock != null ) { 
                    lock.release(); 
                }
            } finally {
                // チャネルを破棄
                if ( channel != null ) { 
                    channel.close(); 
                }
            }
        } finally {
            // ストリームを破棄
            if (  out != null ) { 
                out.close();
            }
        }
    }
}

Lock lock = null;
try {
    // 排他ロック
    lock = new Lock(file);
    
    // 別スレッドで同じファイルを排他ロック
    final Stack<Exception> exceptionStack = new Stack<Exception>();
    Thread t = new Thread( new Runnable() {
        public void run() {
            Lock lock = null;
            try {
                lock = new Lock(file); // ここでブロックする。
            } catch (IOException e) {
                exceptionStack.add(e);// 例外をスタックに覚える。
            } finally {
                if ( lock != null ) {
                    try {
                        lock.close();
                    } catch (IOException e) { e.printStackTrace();}
                }
            }
        }
    });
    
    t.start(); // スレッドスタート
    Thread.sleep(200); // スレッドが開始してブロックするのを待って
    t.interrupt(); // 割り込み! FileLockInterruptionExceptionが発生するはず。
    t.join(); // 完了を待つ
    
    // IO待ち中に割り込みが発生したエラーになっているはず。
    Throwable throwable = exceptionStack.peek().getCause();
    Assert.assertTrue( throwable instanceof FileLockInterruptionException );
    
} finally {
    if ( lock != null ) {
        lock.close();
    }
}

割り込んでも何も起きず、スレッドが終了しないため、次のjoin()で止まる。んー、なんか勘違いしてるのかなー?