分享
 
 
 

控制运行中的application进程实例的个数

王朝java/jsp·作者佚名  2006-01-09
窄屏简体版  字體: |||超大  

在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://blog.csdn.net/youyue/archive/2005/03/22/326477.aspx

此类的源代码如下:

* 创建日期 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();

}

}

}

 
 
 
免责声明:本文为网络用户发布,其观点仅代表作者个人观点,与本站无关,本站仅提供信息存储服务。文中陈述内容未经本站证实,其真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
2023年上半年GDP全球前十五强
 百态   2023-10-24
美众议院议长启动对拜登的弹劾调查
 百态   2023-09-13
上海、济南、武汉等多地出现不明坠落物
 探索   2023-09-06
印度或要将国名改为“巴拉特”
 百态   2023-09-06
男子为女友送行,买票不登机被捕
 百态   2023-08-20
手机地震预警功能怎么开?
 干货   2023-08-06
女子4年卖2套房花700多万做美容:不但没变美脸,面部还出现变形
 百态   2023-08-04
住户一楼被水淹 还冲来8头猪
 百态   2023-07-31
女子体内爬出大量瓜子状活虫
 百态   2023-07-25
地球连续35年收到神秘规律性信号,网友:不要回答!
 探索   2023-07-21
全球镓价格本周大涨27%
 探索   2023-07-09
钱都流向了那些不缺钱的人,苦都留给了能吃苦的人
 探索   2023-07-02
倩女手游刀客魅者强控制(强混乱强眩晕强睡眠)和对应控制抗性的关系
 百态   2020-08-20
美国5月9日最新疫情:美国确诊人数突破131万
 百态   2020-05-09
荷兰政府宣布将集体辞职
 干货   2020-04-30
倩女幽魂手游师徒任务情义春秋猜成语答案逍遥观:鹏程万里
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案神机营:射石饮羽
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案昆仑山:拔刀相助
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案天工阁:鬼斧神工
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案丝路古道:单枪匹马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:与虎谋皮
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:李代桃僵
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:指鹿为马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:小鸟依人
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:千金买邻
 干货   2019-11-12
 
推荐阅读
 
 
 
>>返回首頁<<
 
靜靜地坐在廢墟上,四周的荒凉一望無際,忽然覺得,淒涼也很美
© 2005- 王朝網路 版權所有