|
马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。
您需要 登录 才可以下载或查看,没有帐号?立即注册
x
令人可喜的是java现在已经开源了,所以我想我上述的想法也许有一天会实现,因为java一直都是不断创新的语言,每次创新都会给我们惊喜,这也是我喜欢java的一个原因。application|历程|把持
在C++中很简单完成把持使用程序只能运转一个历程实例,在C#中也很好完成,但在java中想要把持程序的实例数就长短常灾难的事变。究其缘故原由,是由于C++和C#都是经由过程向windows注册表写数据来完成历程互斥,但java是跨平台的,不克不及用这类只能针对windows的办法来完成。
由于java中历程之间十分自力,很少有能够共享的工具,以是只要找到能够在历程间共享的工具,才干完成历程的互斥。有两种工具能够用来完成互斥。一是socket端口,一是文件锁。由于利用socket大概会存在端口被占用的成绩,并且,占用收集端口这类原本就很紧俏的资本来完成互斥也是得失相当的。以是我们这里用第二种工具来完成历程互斥:文件锁。
用文件锁来完成互斥另有一个优点,便可以把持历程实例的个数,好比把持只能运转三个实例或四个实例,而不是像一样平常程序一样牢牢只能运转一个实例。
为了用文件锁完成历程实例数的把持,我这里写了一个InstanceCount类。利用办法以下:
intcount=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-代码款式-代码模板*/packagemytools;
importjava.io.File;importjava.io.FilenameFilter;importjava.io.IOException;importjava.io.RandomAccessFile;importjava.nio.channels.FileChannel;importjava.nio.channels.FileLock;
/***这个类能够用来猎取Java程序的实例数。这里的实例是指运转统一个Java程序所发生的历程实例,而所谓“统一个”是指统一份class文件或jar文件,*假如将这些文件复制至其他地位而从头运转所发生的实例,不属于此类所界说的统一个Java程序发生的实例。**@author由月*@version2005-02-01*/publicclassInstanceCount{privateintcount=0;
privatestaticInstanceCounttheInstance=null;
privateFilefilePath=null;
privateFiletempFile=null;//用来标识本实例的一时文件
privateFileChannelfileChannel=null;
privateFileLockfileLock=null;
privateRandomAccessFileraFile=null;
privateInstanceCount()throwsIOException{//公有的机关子,包管此类没法用new操纵符来创立对象。Stringpath=Path.getPathFromClass(this.getClass());//猎取InstanceCount类的class文件地点路径this.filePath=newFile(path);this.filePath=newFile(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=newRandomAccessFile(this.tempFile,"rw");this.fileChannel=raFile.getChannel();//取得该文件的FileChannel对象this.fileLock=fileChannel.tryLock();//给一时文件加锁,以包管历程实例的独一性this.tempFile.deleteOnExit();if(this.fileLock!=null){this.count++;//新实例发生,实例总数增添1}else{thrownewIOException();}}
privatevoidgetCountAndMax(){File[]fileList=this.filePath.listFiles(newFilenameFilter(){//猎取InstTmp目次下的一时文件列表publicbooleanaccept(Filedir,Stringname){//这里利用了过滤器,只猎取已被加锁了的.tmp文件的列表try{FiletempFile=newFile(dir,name);RandomAccessFileraFile=newRandomAccessFile(tempFile,"rw");FileChannelfileChannel=raFile.getChannel();//取得该文件的FileChannel对象FileLockfileLock=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();returntrue;}else{fileLock.release();raFile.close();tempFile.delete();//将未加锁的和文件名不准确的文件删撤除returnfalse;}}catch(IOExceptione){e.printStackTrace();returnfalse;}}});this.count=fileList.length;}
/***猎取实例数把持对象。一个历程最多能够猎取一个InstanceCount对象。**@return独一的InstanceCount对象*/publicstaticInstanceCountgetInstance(){if(InstanceCount.theInstance==null){//包管本类在一个程序中只要一个实例try{InstanceCountinstCtrl=newInstanceCount();returninstCtrl;}catch(IOExceptione){returnnull;//假如产生IO非常则前往空值}}else{returnInstanceCount.theInstance;}}
/***猎取正在运转中的实例的个数。**@return实例个数。*/publicintgetCount(){getCountAndMax();returnthis.count;}
protectedvoidfinalize(){try{this.fileLock.release();this.fileChannel.close();this.raFile.close();this.tempFile.delete();this.filePath.delete();}catch(IOExceptione){}}
publicstaticvoidmain(String[]args){try{InstanceCountic=InstanceCount.getInstance();System.out.println(ic.getCount());Thread.sleep(5000);}catch(Exceptione){e.printStackTrace();}}}
再举这样一个例子:如果你想对一个数字取绝对值,你会怎么做呢?java的做法是intc=Math.abs(-166);而ruby的做法是:c=-166.abs。呵呵,这就看出了java与ruby的区别。 |
|