S-JIS[2013-12-20/2014-07-19] 変更履歴

ファイルロック

Javaのファイルロックについて。


概要

ファイルをロックすると、他プロセスがそのファイルをロックできなくなる。
これを利用して、二重起動防止のチェックを行うことが出来る。

なお、FileLockのJavadocによると、このファイルロックはプロセス間での排他に使えるが、プロセス内の複数スレッドに対する排他制御には適していないらしい。


ファイルロックは、FileLockを返すオブジェクト(FileChannel)のtryLockメソッドを使用してロックする。
このメソッドは、他プロセスがそのファイルをロック中だとnullを返すので、ロックされているかどうかを判定できる。

FileLockオブジェクトやその元になったFileChannelをクローズしてしまうとロックは解除される。

ファイルをロック中のプロセス(自分が実行しているJavaアプリケーション)が外部からkillされても、ファイルロックは解除される。


JDK1.4の例

FileOutputStreamでファイルを作成し、そのファイルに対してロックする。

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.channels.FileChannel;
import java.nio.channels.FileLock;
	public static void main(String[] args) throws IOException {

		File lockFile = new File("D:/tmp/file-lock-example.lock");

		FileOutputStream fos = new FileOutputStream(lockFile);
		try {
			FileChannel fc = fos.getChannel();
			FileLock lock = fc.tryLock();
			try {
				if (lock == null) {
					// 他プロセスロック中
					throw new RuntimeException(MessageFormat.format("other process locked. file={0}", lockFile));
				}

				// ロック獲得成功
				〜

			} finally {
				if (lock != null) {
					lock.release(); // JDK1.7以降はclose()でも可[2014-07-19]
				}
			}
		} finally {
			fos.close();
		}
	}

JDK1.7の例

FileChannelのopenメソッド(JDK1.7で追加された)を利用する例。
(FileOutputStreamを使わなくてよい)

import java.io.File;
import java.io.IOException;
import java.nio.channels.FileChannel;
import java.nio.channels.FileLock;
import java.nio.file.StandardOpenOption;
	public static void main(String... args) throws IOException {

		File lockFile = new File("D:/tmp/file-lock-example.lock");

		try (FileChannel fc = FileChannel.open(lockFile.toPath(), StandardOpenOption.CREATE, StandardOpenOption.WRITE);
		     FileLock lock = fc.tryLock()) {
			if (lock == null) {
				// 他プロセスロック中
				throw new RuntimeException(MessageFormat.format("other process locked. file={0}", lockFile));
			}

			// ロック獲得成功
			〜
		}
	}

FileLockはJDK1.7でAutoCloseable(closeメソッド)を実装した為、リソース付きtry文が使える。[2014-07-19]
FileLock#close()の中身はrelease()を呼んでいるだけ。


Java目次へ戻る / 新機能へ戻る / 技術メモへ戻る
メールの送信先:ひしだま