程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> JAVA編程 >> 關於JAVA >> 控制運行中的application進程實例的個數

控制運行中的application進程實例的個數

編輯:關於JAVA

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

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved