通过绑定ServerSocket阻止启动Java应用程序的多个实例

时间:2014-07-16 10:32:10

标签: java

我试图通过绑定ServerSocket来阻止启动java应用程序的多个实例。

目前我正在我的主要执行它,如下所示:

public static void main(String[] args) {

    SwingUtilities.invokeLater(new Runnable() {
        public void run() {

            try {
                ServerSocket serverSocket = new ServerSocket(65535, 10);

                showFrame();
            } catch (IOException e1) {
                e1.printStackTrace();
            }
        }
    });
}

它在Eclipse中不起作用我仍然可以打开该应用程序的两个实例。

2 个答案:

答案 0 :(得分:2)

有一些使用网络套接字的人。

  • 如果套接字被其他应用使用怎么办?
  • 如果防火墙发出警告,哪些防病毒附带了什么?

使用独占锁定文件似乎更可靠。

AppLock.java

import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.RandomAccessFile;
import java.nio.channels.FileChannel;
import java.nio.channels.FileLock;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

// http://jimlife.wordpress.com/2008/07/21/java-application-make-sure-only-singleone-instance-running-with-file-lock-ampampampampamp-shutdownhook/
public class AppLock {
    private static File f;
    private static FileChannel channel;
    private static FileLock lock;

    public static boolean lock() {
        try {
            String directory = Utils.getUserDataDirectory();
            String fileName = "jstock.lock";
            Utils.createCompleteDirectoryHierarchyIfDoesNotExist(directory);
            f = new File(directory + fileName);
            // Do we need these code?
            //if (f.exists()) {
            //    f.delete();
            //}
            channel = new RandomAccessFile(f, "rw").getChannel();
            lock = channel.tryLock();
            if(lock == null) {
                channel.close();
                return false;
            }
        } catch (FileNotFoundException ex) {            
            log.error(null, ex);
        } catch (IOException ex) {
            log.error(null, ex);
        }
        return true;
    }

    public static void unlock() {
        // release and delete file lock
        try {
            if (lock != null) {
                lock.release();
                channel.close();
                f.delete();
            }
        } catch(IOException e) {
            log.error(null, e);
        }        
    }

    private static final Log log = LogFactory.getLog(AppLock.class);
}

用法示例

public static void main(String args[]) {        
    if (false == AppLock.lock()) {
        System.exit(0);
    }

    installShutdownHook();

    ...
}

private static void installShutdownHook() {

    Runnable runner = new Runnable() {
        @Override
        public void run() {
            AppLock.unlock();
        }
    };
    Runtime.getRuntime().addShutdownHook(new Thread(runner, "Window Prefs Hook"));
}

请注意,我从开源项目中选择代码段:AppLock.java

答案 1 :(得分:2)

强制执行使用ServerSocket Lock

运行的程序的一个实例

Java代码。把它放到一个名为Main.java的文件中:

import java.net.*;
import java.io.*;
public class Main{
  public static void main(String args[]){
    ServerSocket socket = null;
    try {
      socket = new ServerSocket(34567);
      System.out.println("Doing hard work for 100 seconds");
      try{ Thread.sleep(100000); } catch(Exception e){ }
      socket.close();
    }
    catch (IOException ex) {
      System.out.println("App already running, exiting...");
    }
    finally {
      if (socket != null)
          try{ socket.close(); } catch(Exception e){}
    }
  }
}

编译并运行

javac Main.java
java Main

在正常情况下进行测试:

运行程序。你有100秒的时间在另一个终端再次运行程序,它会说它已经运行了。然后等待100秒,它应该允许你在第二个终端运行它。

强制暂停程序后使用kill -9

进行测试
  1. 在终端1中启动程序。
  2. 在100秒内从另一个终端杀死-9进程。
  3. 再次运行程序,允许它运行。
  4. <强>结论:

    当程序不再运行时,操作系统会清除套接字占用。所以你可以确定程序不会运行两次。

    <强>缺点

    如果一些偷偷摸摸的人,或者一些顽皮的进程要绑定所有端口,或只是你的端口,那么你的程序将无法运行,因为它认为它已经在运行。