控制運行中的application進程實例的個數(shù)
2024-07-21 02:14:16
供稿:網(wǎng)友
在c++中很容易實現(xiàn)控制應(yīng)用程序只能運行一個進程實例,在c#中也很好實現(xiàn),但在java中想要控制程序的實例數(shù)就是非常苦難的事情。究其原因,是因為c++和c#都是通過向windows注冊表寫數(shù)據(jù)來實現(xiàn)進程互斥,但java是跨平臺的,不能用這種只能針對windows的方法來實現(xiàn)。
因為java中進程之間非常獨立,很少有可以共享的東西,所以只有找到可以在進程間共享的東西,才能實現(xiàn)進程的互斥。有兩種東西可以用來實現(xiàn)互斥。一是socket端口,一是文件鎖。因為使用socket可能會存在端口被占用的問題,而且,占用網(wǎng)絡(luò)端口這種本來就很緊俏的資源來實現(xiàn)互斥也是得不償失的。所以我們這里用第二種東西來實現(xiàn)進程互斥:文件鎖。
用文件鎖來實現(xiàn)互斥還有一個好處,即可以控制進程實例的個數(shù),比如控制只能運行三個實例或四個實例,而不是像一般程序一樣緊緊只能運行一個實例。
為了用文件鎖實現(xiàn)進程實例數(shù)的控制,我這里寫了一個instancecount類。使用方法如下:
int count = instancecount.getinstance().getcount();//獲取本程序當(dāng)前已經(jīng)在運行中的進程實例數(shù)。
然后就可以根據(jù)這個count來控制實例數(shù)了,比如:
if(count >3)system.exit(0);
不過這里要注意一個問題,就是java應(yīng)用程序是由一堆class文件組成的,如果在系統(tǒng)中存在這些class的多個拷貝,我認(rèn)為它們是屬于不同的application,即只有用同一的class文件所啟動的進程才算是同一application的不同實例。這個定義如果大家不接受,可以修改我的代碼以符合大家自己的定義。
此類還需要用到另一個類path,這個類在我寫的另一篇文章《獲取類的class文件的絕對路徑 》中有介紹:
http://blog.csdn.net/youyue/archive/2005/03/22/326477.aspx
此類的源代碼如下:
* 創(chuàng)建日期 2005-1-26 * * todo 要更改此生成的文件的模板,請轉(zhuǎn)至 * 窗口 - 首選項 - 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程序的實例數(shù)。 這里的實例是指運行同一個java程序所產(chǎn)生的進程實例, 而所謂“同一個”是指同一份class文件或jar文件, * 如果將這些文件復(fù)制至其他位置而重新運行所產(chǎn)生的實例, 不屬于此類所定義的同一個java程序產(chǎn)生的實例。 * * @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;// 用來標(biāo)識本實例的臨時文件
private filechannel filechannel = null;
private filelock filelock = null;
private randomaccessfile rafile = null;
private instancecount() throws ioexception {// 私有的構(gòu)造子,保證此類無法用new操作符來創(chuàng)建對象。 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()) {// 是否已經(jīng)存在insttmp目錄 getcount(); } else { this.filepath.mkdir(); } this.tempfile = file.createtempfile("~inst", ".tmp", this.filepath);// 創(chuàng)建標(biāo)識本實例的臨時文件 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++;// 新實例產(chǎn)生,實例總數(shù)增加1 } else { throw new ioexception(); } }
private void getcountandmax() { file[] filelist = this.filepath.listfiles(new filenamefilter() {// 獲取insttmp目錄下的臨時文件列表 public boolean accept(file dir, string name) {// 這里使用了過濾器,只獲取已經(jīng)被加鎖了的.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; }
/** * 獲取實例數(shù)控制對象。一個進程最多可以獲取一個instancecount對象。 * * @return 唯一的instancecount對象 */ public static instancecount getinstance() { if (instancecount.theinstance == null) {// 保證本類在一個程序中只有一個實例 try { instancecount instctrl = new instancecount(); return instctrl; } catch (ioexception e) { return null;// 如果發(fā)生io異常則返回空值 } } else { return instancecount.theinstance; } }
/** * 獲取正在運行中的實例的個數(shù)。 * * @return 實例個數(shù)。 */ 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(); } }}