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