Fua*_* S. 87 java single-instance
有时我看到许多应用程序,如msn,windows media player等是单实例应用程序(当用户执行应用程序运行时,将不会创建新的应用程序实例).
在C#中,我使用了Mutex类,但我不知道如何在Java中执行此操作.
小智 62
我在main方法中使用以下方法.这是我见过的最简单,最强大,最少侵入性的方法所以我认为我会分享它.
private static boolean lockInstance(final String lockFile) {
try {
final File file = new File(lockFile);
final RandomAccessFile randomAccessFile = new RandomAccessFile(file, "rw");
final FileLock fileLock = randomAccessFile.getChannel().tryLock();
if (fileLock != null) {
Runtime.getRuntime().addShutdownHook(new Thread() {
public void run() {
try {
fileLock.release();
randomAccessFile.close();
file.delete();
} catch (Exception e) {
log.error("Unable to remove lock file: " + lockFile, e);
}
}
});
return true;
}
} catch (Exception e) {
log.error("Unable to create and/or lock file: " + lockFile, e);
}
return false;
}
Run Code Online (Sandbox Code Playgroud)
Von*_*onC 60
如果我相信这篇文章,请:
让第一个实例尝试在localhost接口上打开侦听套接字.如果它能够打开套接字,则假定这是要启动的应用程序的第一个实例.如果不是,则假设此应用程序的实例已在运行.新实例必须通知现有实例尝试启动,然后退出.现有实例在接收通知后接管,并向处理该操作的侦听器触发事件.
注意:Ahe在评论中提到使用InetAddress.getLocalHost()可能很棘手:
- 它在DHCP环境中无法正常工作,因为返回的地址取决于计算机是否具有网络访问权限.
解决方案是打开连接InetAddress.getByAddress(new byte[] {127, 0, 0, 1});
可能与bug 4435662有关.
getLocalHost:返回机器的IP地址,与实际结果:返回127.0.0.1. 令人惊讶的是在Linux上获得
getLocalHost回报127.0.0.1但在Windows上却没有.
或者你可以使用 ManagementFactory对象.正如解释在这里:
该
getMonitoredVMs(int processPid)方法接收当前应用程序PID作为参数,并捕获从命令行调用的应用程序名称,例如,应用程序从c:\java\app\test.jar路径启动,然后值变量为"c:\\java\\app\\test.jar".这样,我们将在下面代码的第17行捕获应用程序名称.
之后,我们在JVM中搜索具有相同名称的另一个进程,如果我们找到它并且应用程序PID不同,则意味着它是第二个应用程序实例.
JNLP也提供了一个 SingleInstanceListener
如果应用程序.有一个GUI,用JWS启动它并使用SingleInstanceService.看演示.用于(演示和.)示例代码的SingleInstanceService.
小智 6
是的,对于eclipse来说,这是一个非常不错的答案.下面的RCP eclipse单实例应用程序是我的代码
在application.java中
if(!isFileshipAlreadyRunning()){
MessageDialog.openError(display.getActiveShell(), "Fileship already running", "Another instance of this application is already running. Exiting.");
return IApplication.EXIT_OK;
}
private static boolean isFileshipAlreadyRunning() {
// socket concept is shown at http://www.rbgrn.net/content/43-java-single-application-instance
// but this one is really great
try {
final File file = new File("FileshipReserved.txt");
final RandomAccessFile randomAccessFile = new RandomAccessFile(file, "rw");
final FileLock fileLock = randomAccessFile.getChannel().tryLock();
if (fileLock != null) {
Runtime.getRuntime().addShutdownHook(new Thread() {
public void run() {
try {
fileLock.release();
randomAccessFile.close();
file.delete();
} catch (Exception e) {
//log.error("Unable to remove lock file: " + lockFile, e);
}
}
});
return true;
}
} catch (Exception e) {
// log.error("Unable to create and/or lock file: " + lockFile, e);
}
return false;
}
Run Code Online (Sandbox Code Playgroud)
我们使用文件锁定(在用户的app数据目录中获取魔术文件的独占锁定),但我们主要感兴趣的是防止多个实例运行.
如果你试图让第二个实例将命令行args等传递给第一个实例,那么在localhost上使用套接字连接就会一举两得.一般算法:
我找到了一个解决方案,有点卡通化的解释,但在大多数情况下仍然有效.它使用普通的旧锁文件创建东西,但是在一个完全不同的视图中:
http://javalandscape.blogspot.com/2008/07/single-instance-from-your-application.html
我认为这对那些拥有严格防火墙设置的人有帮助.
您可以使用JUnique库.它为运行单实例java应用程序提供支持,并且是开源的.
http://www.sauronsoftware.it/projects/junique/
JUnique库可用于防止用户同时运行同一Java应用程序的更多实例.
JUnique实现了由同一用户启动的所有JVM实例之间共享的锁和通信通道.
public static void main(String[] args) {
String appId = "myapplicationid";
boolean alreadyRunning;
try {
JUnique.acquireLock(appId, new MessageHandler() {
public String handle(String message) {
// A brand new argument received! Handle it!
return null;
}
});
alreadyRunning = false;
} catch (AlreadyLockedException e) {
alreadyRunning = true;
}
if (!alreadyRunning) {
// Start sequence here
} else {
for (int i = 0; i < args.length; i++) {
JUnique.sendMessage(appId, args[0]));
}
}
}
Run Code Online (Sandbox Code Playgroud)
在引擎盖下,它在%USER_DATA%/.junique文件夹中创建文件锁,并在随机端口为每个允许在Java应用程序之间发送/接收消息的唯一appId创建服务器套接字.
| 归档时间: |
|
| 查看次数: |
58557 次 |
| 最近记录: |