如何允许Java程序一次只运行一个实例?
-
06-09-2019 - |
题
我需要防止用户多次启动我的 Java 应用程序(WebStart Swing 应用程序)。因此,如果应用程序已经在运行,则不应再次启动它或显示警告/再次关闭。
有没有一些方便的方法来实现这一目标?我考虑过阻止端口或将某些内容写入文件。但希望您可以访问一些系统属性或 JVM?
顺便提一句。目标平台是带有 Java 1.5 的 Windows XP
解决方案
我觉得你打开一个端口,当你启动应用程序,听取的建议是最好的主意。
这是很容易做到的,你不必担心清除它,当你关闭你的应用程序。例如,如果你写一个文件,但有人再杀死使用任务管理器中的文件的进程不会被删除。
另外,如果我没记错的话是需要有一个Java进程的PID从JVM内部,所以不要尝试使用的PID制定一个解决方案没有简单的方法。
这样的事情应该达到目的:
private static final int PORT = 9999;
private static ServerSocket socket;
private static void checkIfRunning() {
try {
//Bind to localhost adapter with a zero connection queue
socket = new ServerSocket(PORT,0,InetAddress.getByAddress(new byte[] {127,0,0,1}));
}
catch (BindException e) {
System.err.println("Already running.");
System.exit(1);
}
catch (IOException e) {
System.err.println("Unexpected error.");
e.printStackTrace();
System.exit(2);
}
}
此示例代码明确地结合到127.0.0.1
应避免任何防火墙警告,该地址的任何业务,必须从本地系统。
在选择一个端口尽量避免一个公知的端口的列表中提及 。理论上,应该使端口在文件或经由在冲突情况下,一个命令行开关使用可配置的。
其他提示
由于问题表明正在使用 WebStart,因此显而易见的解决方案是使用 javax.jnlp.SingleInstanceService
.
该服务在 1.5 中可用。请注意,1.5 目前已接近其使用寿命结束期。开始使用 Java SE 6!
我认为更好的主意是使用文件锁(一个很旧的想法:))。由于Java 1.4中引入/ O库一个新的我,允许文件锁定。
一旦应用程序启动时,它试图获取对文件锁(或创建它,如果它不存在),当应用程序退出锁relased。如果应用程序不能获得锁,它退出。
怎么办文件锁定的示例是例如在 Java开发年鉴
如果你想使用文件锁定在Java Web Start应用或者小程序,你需要唱的应用程序或小程序。
我们通过创建一个籽粒互斥对象,并在启动寻找它做在C ++相同的。的优点是与使用一个插座,即,当进程死亡/崩溃/退出/是杀死,互斥对象是由内核清理。
我不是一个Java程序员,所以我不知道你是否可以做这样的事情在Java中?
您可以使用JUnique库。它提供了支持用于运行单实例java应用程序和是开源。
http://www.sauronsoftware.it/projects/junique/
另请参见我在完整的答案如何实现的单个实例的Java应用程序?
我已经创建跨平台的AppLock类。
HTTP://rumatoest.blogspot的.com / 2015/01 / HOWTO - 运行 - 仅单java的application.html
它是使用文件锁定技术。
更新。在2016年10月14日我已经创建包兼容与Maven / gradle这个 https://github.com/jneat/ jneat 并解释在这里 HTTP:/ /rumatoest.blogspot.com/2015/06/synchronize-code-over-multiple-jvm.html
您可以使用注册表,虽然这半心半意违背了使用Java等高级语言的目的。至少目标平台是窗口= d
尝试JUnique:
String appId = "com.example.win.run.main";
boolean alreadyRunning;
try {
JUnique.acquireLock(appId);
alreadyRunning = false;
} catch (AlreadyLockedException e) {
alreadyRunning = true;
}
if (alreadyRunning) {
Sysout("An Instance of this app is already running");
System.exit(1);
}
我见过这么多的这个问题,我一直在寻找解决,这并不需要与防火墙碰撞或进入插座的东西的机会与平台无关的方式同样的问题。
所以,这里是我所做的:
import java.io.File;
import java.io.IOException;
/**
* This static class is in charge of file-locking the program
* so no more than one instance can be run at the same time.
* @author nirei
*/
public class SingleInstanceLock {
private static final String LOCK_FILEPATH = System.getProperty("java.io.tmpdir") + File.separator + "lector.lock";
private static final File lock = new File(LOCK_FILEPATH);
private static boolean locked = false;
private SingleInstanceLock() {}
/**
* Creates the lock file if it's not present and requests its deletion on
* program termination or informs that the program is already running if
* that's the case.
* @return true - if the operation was succesful or if the program already has the lock.<br>
* false - if the program is already running
* @throws IOException if the lock file cannot be created.
*/
public static boolean lock() throws IOException {
if(locked) return true;
if(lock.exists()) return false;
lock.createNewFile();
lock.deleteOnExit();
locked = true;
return true;
}
}
使用System.getProperty(“java.io.tmpdir”)的锁文件路径可以确保您总是在同一个地方创建锁。
然后,在你的程序你只需要调用是这样的:
blah blah main(blah blah blah) {
try() {
if(!SingleInstanceLock.lock()) {
System.out.println("The program is already running");
System.exit(0);
}
} catch (IOException e) {
System.err.println("Couldn't create lock file or w/e");
System.exit(1);
}
}
这确实对我来说。现在,如果你杀了该程序不会删除锁文件,但你可以通过编写程序的PID到锁文件,使锁()方法,检查如果该进程已经运行解决这个问题。这是留给有兴趣的人士的assingment。 :)