在C++中很容易实现控制应用程序只能运行一个进程实例,在C#中也很好实现,但在java中想要控制程序的实例数就是非常苦难的事情。究其原因,是因为C++和C#都是通过向windows注册表写数据来实现进程互斥,但java是跨平台的,不能用这种只能针对windows的方法来实现。
因为java中进程之间非常独立,很少有可以共享的东西,所以只有找到可以在进程间共享的东西,才能实现进程的互斥。有两种东西可以用来实现互斥。一是socket端口,一是文件锁。因为使用socket可能会存在端口被占用的问题,而且,占用网络端口这种本来就很紧俏的资源来实现互斥也是得不偿失的。所以我们这里用第二种东西来实现进程互斥:文件锁。
用文件锁来实现互斥还有一个好处,即可以控制进程实例的个数,比如控制只能运行三个实例或四个实例,而不是像一般程序一样紧紧只能运行一个实例。
为了用文件锁实现进程实例数的控制,我这里写了一个InstanceCount类。使用方法如下:
int count = InstanceCount.getInstance().getCount();//获取本程序当前已经在运行中的进程实例数。
然后就可以根据这个count来控制实例数了,比如:
if(count >3)System.exit(0);
不过这里要注意一个问题,就是java应用程序是由一堆class文件组成的,如果在系统中存在这些class的多个拷贝,我认为它们是属于不同的application,即只有用同一的class文件所启动的进程才算是同一application的不同实例。这个定义如果大家不接受,可以修改我的代码以符合大家自己的定义。
此类还需要用到另一个类Path,这个类在我写的另一篇文章《获取类的class文件的绝对路径 》中有介绍:
http://c-zhiwu.iteye.com/admin/blogs/814110
此类的源代码如下:
/* 创建日期 2005-1-26
*
* TODO 要更改此生成的文件的模板,请转至
* 窗口 - 首选项 - Java - 代码样式 - 代码模板
*/
package mytools;
import java.io.File;
import java.io.FilenameFilter;
import java.io.IOException;
import java.io.RandomAccessFile;
import java.nio.channels.FileChannel;
import java.nio.channels.FileLock;
/**
* 这个类可以用来获取Java程序的实例数。 这里的实例是指运行同一个Java程序所产生的进程实例, 而所谓“同一个”是指同一份class文件或jar文件,
* 如果将这些文件复制至其他位置而重新运行所产生的实例, 不属于此类所定义的同一个Java程序产生的实例。
*
* @author 由月
* @version 2005-02-01
*/
public class InstanceCount {
private int count = 0;
private static InstanceCount theInstance = null;
private File filePath = null;
private File tempFile = null;// 用来标识本实例的临时文件
private FileChannel fileChannel = null;
private FileLock fileLock = null;
private RandomAccessFile raFile = null;
private InstanceCount() throws IOException {// 私有的构造子,保证此类无法用new操作符来创建对象。
String path = Path.getPathFromClass(this.getClass());// 获取InstanceCount类的class文件所在路径
this.filePath = new File(path);
this.filePath = new File(this.filePath.getParent(), "InstTmp");
if (this.filePath.exists() && this.filePath.isDirectory()) {// 是否已经存在InstTmp目录
getCount();
} else {
this.filePath.mkdir();
}
this.tempFile = File.createTempFile("~Inst", ".tmp", this.filePath);// 创建标识本实例的临时文件
this.raFile = new RandomAccessFile(this.tempFile, "rw");
this.fileChannel = raFile.getChannel();// 获得该文件的FileChannel对象
this.fileLock = fileChannel.tryLock();// 给临时文件加锁,以保证进程实例的唯一性
this.tempFile.deleteOnExit();
if (this.fileLock != null) {
this.count++;// 新实例产生,实例总数增加1
} else {
throw new IOException();
}
}
private void getCountAndMax() {
File[] fileList = this.filePath.listFiles(new FilenameFilter() {// 获取InstTmp目录下的临时文件列表
public boolean accept(File dir, String name) {// 这里使用了过滤器,只获取已经被加锁了的.tmp文件的列表
try {
File tempFile = new File(dir, name);
RandomAccessFile raFile = new RandomAccessFile(
tempFile, "rw");
FileChannel fileChannel = raFile.getChannel();// 获得该文件的FileChannel对象
FileLock fileLock = null;
if (InstanceCount.this.tempFile != null
&& name.equals(InstanceCount.this.tempFile
.getName())) {
} else {
fileLock = fileChannel.tryLock();
}
if (tempFile.isFile()
&& name.endsWith(".tmp")
&& (fileLock == null || fileLock.isValid() == false)) {
raFile.close();
return true;
} else {
fileLock.release();
raFile.close();
tempFile.delete();// 将未加锁的和文件名不正确的文件删除掉
return false;
}
} catch (IOException e) {
e.printStackTrace();
return false;
}
}
});
this.count = fileList.length;
}
/**
* 获取实例数控制对象。一个进程最多可以获取一个InstanceCount对象。
*
* @return 唯一的InstanceCount对象
*/
public static InstanceCount getInstance() {
if (InstanceCount.theInstance == null) {// 保证本类在一个程序中只有一个实例
try {
InstanceCount instCtrl = new InstanceCount();
return instCtrl;
} catch (IOException e) {
return null;// 如果发生IO异常则返回空值
}
} else {
return InstanceCount.theInstance;
}
}
/**
* 获取正在运行中的实例的个数。
*
* @return 实例个数。
*/
public int getCount() {
getCountAndMax();
return this.count;
}
protected void finalize() {
try {
this.fileLock.release();
this.fileChannel.close();
this.raFile.close();
this.tempFile.delete();
this.filePath.delete();
} catch (IOException e) {
}
}
public static void main(String[] args) {
try {
InstanceCount ic = InstanceCount.getInstance();
System.out.println(ic.getCount());
Thread.sleep(5000);
} catch (Exception e) {
e.printStackTrace();
}
}
}
本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/youyue/archive/2005/03/22/326549.aspx
分享到:
相关推荐
C# 只能运行一个winForm进程是指在C#中实现单实例应用程序,确保同一个应用程序只能运行一个实例,以避免资源浪费和混乱。下面将详细介绍如何实现单实例应用程序。 单实例应用程序的实现 在C#中,实现单实例应用...
在IT领域,进程控制是操作系统的核心功能之一,它涉及到如何创建、管理、监控以及结束操作系统中的进程。在本文中,我们将深入探讨如何通过编程来控制系统进程,特别是在Windows环境下,使用.NET框架提供的API来实现...
这意味着如果你有两个不同的LabVIEW可执行文件,它们各自运行在一个单独的进程中,那么在其中一个进程中创建的队列或信号量无法被另一个进程识别。如果需要在这两个可执行文件之间共享数据或状态,则需要使用其他跨...
互斥量是一种同步对象,用于在多线程或多进程环境中控制对共享资源的访问。在VB中,我们可以利用互斥量来确保只有一个程序实例正在运行。 以下是一个简单的VB实现步骤: 1. **导入System.Threading命名空间**:在...
### 安全彻底关闭实例Excel.Application后产生的进程方法 在.NET框架中,通过COM互操作技术,我们可以方便地操作Microsoft Office应用程序,例如Excel。但在实际应用过程中,经常会遇到因为资源释放不当导致的进程...
Java Application-J2SE实例基础程序是Java编程领域中的核心部分,主要关注于桌面应用程序的开发。J2SE,即Java 2 Platform, Standard Edition,是Java平台的标准版,提供了开发和运行桌面应用、服务器端应用以及网络...
C# FORM单实例运行机制是指在一个应用程序中,限制只能启动一个进程实例,以避免多个进程同时运行造成的混乱和资源浪费。今天我们将探讨两种实现C# FORM单实例运行机制的方法。 方法一:使用Mutex限制多个进程运行 ...
在编程领域,特别是Windows应用程序开发中,经常需要确保一个程序只能有一个实例运行,避免用户无意或有意地启动多个进程导致资源浪费或数据冲突。易语言API禁止运行多个实例的源码就是解决这个问题的一种方法。...
在这个特定的案例中,描述中提到提供了一个已经封装好的jar包,这可能是为了解决在Android 5.0及以上版本无法直接获取运行进程的问题。这个jar包可能包含了实现绕过限制、获取运行进程信息的替代方法。使用这样的第...
在"ex6.6_application"实例中,我们可能会遇到数据库连接、用户认证、会话管理等常见应用场景。通过这个实例,学习者可以学习如何使用JDBC进行数据库操作,如何使用session来跟踪用户状态,以及如何处理表单提交和...
以上就是使用`Application`来实现Android完全退出系统实例的主要步骤和知识点。需要注意的是,强制结束应用进程可能会导致数据丢失或用户体验问题,因此在实际开发中需谨慎处理。此外,Android系统通常不鼓励开发者...
2. **刷新列表**:此功能用于显示当前计算机中所有运行的进程信息。首先,清空`ListView`控件以准备添加新的进程数据。然后,调用`Process.GetProcesses()`静态方法获取系统中所有活动进程的数组。对于数组中的每一...
Excel VBA Application 对象应用实例 Application 对象是 VBA 编程中一个非常重要的对象,它代表整个 Microsoft Excel 应用程序,带有 175 个属性和 52 个方法,可以设置整个应用程序的环境或配置应用程序。 首先...
在IT行业中,自动化运行Word宏是一项非常实用的技术,特别是在处理大量文档、格式转换或执行重复任务时。这个“使用自动化运行Word宏编程实例锦集”是针对C++.NET开发者的一个资源,通过Visual Studio.NET环境进行...
在IT行业中,尤其是在软件开发领域,我们经常遇到需要确保应用程序只能有一个实例运行的情况。这通常被称为单例模式。本文将详细讲解如何使用C#和WPF(Windows Presentation Foundation)实现只允许一个实例运行的...
在Windows API中,`EnumProcesses`函数可以用来获取当前系统中运行的所有进程ID。你需要定义一个足够大的缓冲区来存储这些ID,然后调用该函数。获取到进程ID后,你可以使用`OpenProcess`函数获取进程句柄,这个句柄...
这种方法通过获取系统中所有正在运行的进程,并检查其中是否有与当前进程名称相同的进程。如果存在,则表明已经有实例正在运行。 ```csharp static void Main() { int ProceedingCount = 0; Process[] ...
"进程管理"是指操作系统对正在运行的程序实例的管理和控制,包括创建、调度、资源分配、同步和通信等。在C#中,我们可以使用`System.Diagnostics`命名空间中的类来实现这些功能。其中,`Process`类是核心,它提供了...
在C#编程中,有时我们需要确保我们的应用程序在操作系统上始终只有一个实例在运行。这通常用于控制资源使用,防止多个窗口的混乱,或者确保数据的一致性。这种限制应用程序实例数量的技术被称为“单例模式”。本篇...
API(Application Programming Interface)是指软件系统提供给开发者用于构建应用的接口,而“禁止运行多个实例”通常是指程序设计中的一种策略,确保同一时间只能有一个程序实例在运行。 在易语言中,实现这一功能...