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

application|进程|控制

    在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();  } }}

时间: 2024-11-03 19:57:39

控制运行中的application进程实例的个数的相关文章

《深入理解Nginx:模块开发与架构解析》一第2章 Nginx的配置2.1 运行中的Nginx进程间的关系

第2章 Nginx的配置 Nginx拥有大量官方发布的模块和第三方模块,这些已有的模块可以帮助我们实现Web服务器上很多的功能.使用这些模块时,仅仅需要增加.修改一些配置项即可.因此,本章的目的是熟悉Nginx的配置文件,包括配置文件的语法格式.运行所有Nginx服务必须具备的基础配置以及使用HTTP核心模块配置静态Web服务器的方法,最后还会介绍反向代理服务器. 通过本章的学习,读者可以:熟练地配置一个静态Web服务器:对影响Web服务器性能的各个配置项有深入的理解:对配置语法有全面的了解.通

Linux中如何让进程在后台运行

一. nohup / setsid / & 使用场景:如果只是临时有一个命令需要长时间运行,什么方法能最简便的保证它在后台稳定运行呢? 我们的解决办法就有两种途径:要么让进程忽略 HUP 信号,要么让进程运行在新的会话里从而成为不属于此终端的子进程. 解决方法: 1.nohup 只需在要处理的命令前加上 nohup 即可,标准输出和标准错误缺省会被重定向到 nohup.out 文件中.一般我们可在结尾加上"&"来将命令同时放入后台运行,也可用>filename 2

Win7运行中出现“错误1079:此服务的帐户不同于运行于同一进程上的其他服务的帐户”

Windows 7在开启服务时出现"错误1079:此服务的帐户不同于运行于同一进程上的其他服务的帐户"的提示,如下图所示:   原因分析: 此故障通常在由svchost服务宿主进程所启动的服务上发生,Windows 7最多可以启动七个svchost进程实例,分别负责启动一组服务.一组服务中的每个服务必须和对应的svchost进程实例运行在同一个启动帐户下.例如Alert服务属于Local  Service组的服务,其对应的svchost进程实例运行在Local Service帐户下,如

Linux系统中的ps进程查看命令使用实例集锦

  linux 中ps命令是Process Status的缩写.ps命令可以列出系统中当前运行的进程,所列出的进程是执行ps命令这个时刻正在运行的进程. 如果要动态显示进程信息,需要使用top命令. 通过ps命令,可以确定哪些进程正在运行和运行状态.进程是否结束.进程是否僵死,哪些进程占用过多资源等. 要杀死进程,使用kill命令,例:kill 12345 (12345为进程的pid) linux进程有5种状态 1.运行(正在运行或在运行队列中等待) 2.中断(休眠中,受阻,或等待某个条件的形成

Erlang中的注册进程使用实例_Erlang

之前看到 Erlang 中的注册进程时,对注册并不理解,主要是不理解注册的原子的作用域.刚才突然想明白了: 复制代码 代码如下: 注册进程关联的原子具有全局作用域 也就是说关联了注册进程之后的原子可以全局被使用 Erlang 中的并发机制是通过消息邮箱实现的,进程间进行通讯的方式只有消息邮箱,而进程间通讯需要知道进程的进程号,而使用 spawn 产生新进程时会返回新进程的进程号供使用. 一个最简单的进程间通信的程序如下 复制代码 代码如下: -module(test). start() ->  

详解Linux系统中的守护进程

守护进程daemon,是生存期较长的一种进程.它们常常在系统自举时启动,仅在系统关闭时才终止.因为它们没有控制终端,所以说它们是在后台运行的.UNIX系统有很多守护进程,它们执行日常事务活动. 1.系统自举 自举(bootstrapping)一词来自于人都是靠自身的"自举"机构站立起来的这一思想.计算机必须具备自举能力将自己所有的元件激活,以便能完成加载操作系统这一目的,然后再由操作系统承担起那些单靠自举代码无法完成的更复杂的任务. 自举只有两个功能:加电自检和磁盘引导. 加电自检:当

渗透测试中的Application Verifier(DoubleAgent利用介绍)

本文讲的是渗透测试中的Application Verifier(DoubleAgent利用介绍), 0x00 前言 近日,Cybellum Technologies LTD公开了一个0-day漏洞的POC,对其命名为"DoubleAgent",可用于控制主流的杀毒软件. 不同于以往的绕过思路,这次使用的是一种直接攻击并劫持的方式,本文将要介绍该方式的原理,分享利用思路.攻击条件和防御方法 0x01 简介 该方式主要是对微软系统自带的Application Verifier(应用程序检验

C语言编写Linux守护进程实例_C 语言

守护进程(Daemon)是运行在后台的一种特殊进程.它独立于控制终端并且周期性地执行某种任务或等待处理某些发生的事件.守护进程是一种很有用的进 程.Linux的大多数服务器就是用守护进程实现的.比如,Internet服务器inetd,Web服务器httpd等.同时,守护进程完成许多系统任 务.比如,作业规划进程crond,打印进程lpd等. 守护进程的编程本身并不复杂,复杂的是各种版本的Unix的实现机制不尽相同,造成不同Unix环境下守护进程的编程规则并不一致.这需要读者注意,照搬 某些书上的

Node.js V0.12新特性之在单进程中跑多个实例

实例 经常有人提出,希望Node.js能被嵌入到其他程序中,特别是让它能跟其他事件循环整合而且(与此同时)支持多个Node执行情境:也就是说让多个Node实例在同一个进程中和平共处的能力.想象一下,比如有个node-webkit 程序,每个窗口都运行在自己的Node实例上,各窗口彼此相互独立.或者把Node嵌在手机或网络交换机里,处理多连接的路由逻辑,但却只是在单个进程中,并且不久的将来就能实现. 一个客户找到我们,说他们的程序需要这类功能.他们经过调研,肯定了我们在Node核心和libuv上的