보통 프로그램의 실행 시킬 때 단 하나의 프로세스만을 허용해야 할 경우가 있습니다. 자바에서는 이런 요구사항을 어떻게 해결 할까요?? NIO의 FileLock클래스를 이용하는 방법이 있습니다. NIO의 FileLock은 파일에 락을 걸어서 JVM 간의 파일 동기화를 시켜주는 클래스 입니다. 그러니까 oneProcessTest라는 자바 프로그램이 있다고 가정을 하죠. oneProcessTest를 실행 시키면 JVM에서 oneProcessTest 클래스를 로드하게 됩니다. 그럼 oneProcessTest 클래스 내부에서 FileLock 크래스를 이용해 특정 파일을 특정 경로에 쓰고 이 파일에 대해 락을 획득합니다. 만약에 특정 파일에 대해서 락을 획득하려고 하는데 획득이 되지 않으면 이미 다른 JVM에서 oneProcessTest를 실행 시킨것으로 간주하고 현재 시도한 oneProcessTest의 실행을 중지 시킵니다. 아참, FiileLock 클래스를 사용 시 주의할 점은 같은 JVM 내부의 쓰레드 간의 동기화를 이루어지지 않습니다. 자세한 내용은 NIO의 FileLock에 대해서 공부하시기 바랍니다.
예제 소스코드 말미에 보시면 아래와 같은 코드가 있는 것을 보실 수 가 있습니다. 이 코드는 프로그램이 종료 시 실행 될 내용을 등록하는 것입니다. 자세한 내용은 놀새 ~ 님 블로그에 잘 정리가 되어있네요 ~ 꼭 한 번 들러서 내용을 읽어보세요 ^^
Shutdown shutdownHook = new HookShutdown();
Runtime.getRuntime().addShutdownHook(shutdownHook);
import java.io.File;
import java.io.IOException;
import java.io.RandomAccessFile;
import java.nio.channels.FileChannel;
import java.nio.channels.FileLock;
import javax.swing.JOptionPane;
public class ExecuteOneProcessTest {
private static File f;
private static FileChannel channel;
private static FileLock lock;
protected static boolean isRunnable() {
boolean runnable = false;
try {
String path = System.getProperty("user.home") + File.separator + oneProcessTest.lock";
f = new File(path);
// 파일이 존재하면 삭제를 시도합니다. 다른 JVM에서 파일의 Lock을 획득하고 있다면 파일은 지워지지
// 않습니다.
if (f.exists()) {
f.delete();
}
// 파일을 생성하여 채널 객체를 얻습니다.
channel = new RandomAccessFile(f, "rw").getChannel();
// lock 을 시도합니다.
lock = channel.tryLock();
// lock이 null이라는 것은 다른 JVM에서 이미 파일의 lock을 획득했다는 것입니다. 따라서 채널을 종료하고
// 예외를 발생시켜 runnable의 값을 false로 유지시킵니다.
if (lock == null) {
channel.close();
throw new Exception();
}
// Add shutdown hook to release lock when application shutdown
HookShutdown shutdownHook = new HookShutdown();
Runtime.getRuntime().addShutdownHook(shutdownHook);
runnable = true;
} catch (Exception e) {
}
return runnable;
}
// lock을 풀고 파일을 제거 합니다.
public static void unlockFile() {
try {
if (lock != null) {
lock.release();
channel.close();
f.delete();
System.out.println("Shutdown & Unlock finish successfully.");
}
} catch (IOException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
}
// 프로세스가 종료 될 때 실행 될 작업을 등록 할 클래스
static class HookShutdown extends Thread {
public void run() {
unlockFile();
}
}
/**
* @param args
*/
public static void main(String[] args) throws Exception {
if(!isRunnable()) {
JOptionPane.showMessageDialog(null, "ExecuteOneProcessTest already has started. The program will be closed.", "Error", JOptionPane.ERROR_MESSAGE);
return;
}
Thread.sleep(5000);
}
}
'Language > Java' 카테고리의 다른 글
[펌] RandomAccessFile과 BufferedReader의 한계점과 해결 방안 (0) | 2012.05.21 |
---|---|
Start java application in background mode on Window (0) | 2012.05.06 |
[펌] Interrupting Java threads (0) | 2012.04.03 |
[펌] Shutting Down Threads Cleanly (0) | 2012.04.03 |
Java String ltrim & rtrim (0) | 2012.03.14 |