2008년 10월 16일
프로그램의 프로세스를 하나만 허용하기

 보통 프로그램의 실행 시킬 때 단 하나의 프로세스만을 허용해야 할 경우가 있습니다. 자바에서는 이런 요구사항을 어떻게 해결 할까요?? 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[] argsthrows Exception {

    if(!isRunnable()) {

      JOptionPane.showMessageDialog(null, "ExecuteOneProcessTest already has started. The program will be closed.""Error", JOptionPane.ERROR_MESSAGE);

      return;
    }

    
Thread.sleep(5000);
  }
}



예제 프로젝트 다운로드 : ExecuteOneProcessTest.zip


 


by greenfrog | 2008/10/16 23:18 | JAVA | 트랙백(1) | 덧글(2)
트랙백 주소 : http://greenfrog7.egloos.com/tb/964959
☞ 내 이글루에 이 글과 관련된 글 쓰기 (트랙백 보내기) [도움말]
Tracked from Start!!! at 2009/03/16 15:38

제목 : 자바로 작성된 프로그램 단 한번만 실행하기(2)
구글링을 하다 접한 greenfrog님의 블로그에서 본 놀라운 기술.. 지금까지 접했던 것과는 차원이 달랐다. 파일을 생성하고 파일의 channel을 받아와서 파일을 lock거는 방법은 놀라울 따름이다. 재밌는 기술을 배웠다.....more

Commented by neptunex at 2009/03/26 17:52
좋은 정보 감사합니다. 다음에 써먹어야 겠네요..ㅋㅋ
Commented by 이재욱 at 2010/10/29 09:31
우연히 찾게됐습니다만, 좋은 자료 고맙습니다.. 역시 나의 한계는 있어도 프로그래밍의 한계는 없는것 같습니다. ^^

:         :

:

비공개 덧글



<< 이전 페이지 | 다음 페이지 >>