java.net.ServerSocke让java程序只运行一个实例
来源:互联网 发布:虎牙银豆淘宝怎么交易 编辑:程序博客网 时间:2024/06/05 09:17
问题提出:
一个程序可以在内存里面存在多个运行实例,比如可打开多个Word程序。但是,有时仅需运行的实例只有一个,也就是说,该程序同一时刻在内存里面运行的只有一个实例。这样当这个程序在内存中已经存在一个运行实例而用户又再次运行了该程序的时候,有两种结果,第一种结果是结束目前的运行实例,打开新运行的实例;第二种就是让新运行的实例退出,原有的运行实例继续运行。
解决方法1:
因为任何时候只有一个实例,所以在实现这种功能的时候必须借助只能被独享的资源。如果我们的程序是基于某个平台的,那么就可以借助操作系统的内核对象来完成,比如Windows操作系统就提供了CreateMutex这个API来创建一个独享的内核对象。但是因为要考虑平台无关,Java程序的实例控制不应该使用系统的内核对象来完成,那么我们就必须找到其它的、可以独享的资源。实际上,一台机器无论是在什么操作系统上,网络端口都是独享的,也就是说基于网络端口这个独享的原理,我们可以很方便地让我们的Java程序实现在内存里面只有一个运行实例这个功能,而且这个功能的实现是与平台无关的
在实例化java.net.ServerSocke时利用java.net.BindException异常来判断java程序是否已经运行:
import java.io.*;
import java.net.*;
public class OneInstance {
private static ServerSocket listenerSocket;
public static void main(String[] args) {
try {
listenerSocket = new ServerSocket(20004);
//At this point, no other socket may listen on port 20004.
} catch(java.net.BindException e) {
System.err.println("A previous instance is already running....");
System.exit(1);
} catch(final IOException e) { // an unexpected exception occurred
System.exit(1);
}
// Do some work here.....
}
}
扩展:
上面的程序也许有一个小bug,就是如果程序在开始运行时ServerSocket监听的端口已经被其它程序占用,那么程序的运行就会受到影响。所以程序的端口应该尽量取得大一些,在这种情况下其它程序占用这个程序使用的端口的概率是可以忽略不计的。同时,还可以做两种扩展,第一种是把端口写在配置文件中,可通过读配置文件得到端口,这样就能够在其它程序占用目前端口的情况下改变这个程序使用的端口。还有一种是在运行的时候用两个端口监听,只要有一个所监听的端口被占用就做出响应,这样两个端口都被其它程序占用的概率就更加的微乎其微了。
改进:
import java.io.*;
import java.net.*;
import java.io.*;
import java.net.*;
public class OneInstance {
private static ServerSocket listenerSocket1;
private static ServerSocket listenerSocket2;
public static void main(String[] args) {
shortlistenerSocketFlagNum=0;
try {
listenerSocket1= new ServerSocket(20004);
//At this point, no other socket may listen on port 20004.
} catch(java.net.BindException e) {
//System.err.println("A previous instance is already running....");
listenerSocketFlagNum=1;
} catch(final IOException e) { // an unexpected exception occurred
System.exit(1);
}
try {
listenerSocket2= new ServerSocket(30004);
//At this point, no other socket may listen on port 20004.
} catch(java.net.BindException e) {
//System.err.println("A previous instance is already running....");
listenerSocketFlagNum=2;
} catch(final IOException e) { // an unexpected exception occurred
System.exit(1);
}
System.err.println("A previous instance is already running....");
System.exit(1);
}
// Do some work here.....
}
}
解决方法2:
利用NIO提出的文件锁,可以在读取一个文件时,获得文件锁,这个锁应该是系统维护的,JVM应该是调用的系统文件锁机制,例子如下:
Code highlighting produced by Actipro CodeHighlighter (freeware)
http://www.CodeHighlighter.com/
-->import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.RandomAccessFile;
import java.nio.channels.FileChannel;
import java.nio.channels.FileLock;
/**
*
* @author vma
*/
public class temp1 {
public static void main(String args[]) throws FileNotFoundException, InterruptedException, IOException{
RandomAccessFile r = new RandomAccessFile("d://testData.java","rw");
FileChannel temp = r.getChannel();
FileLock fl = temp.lock();
System.out.println(fl.isValid());
Thread.sleep(100000);
temp.close();
} 当代码获得锁后:我们试图编辑这个文件是就会:
如果在启动一个Java Main方法时:
public class temp2 {public static void main(String args[]) throws FileNotFoundException, InterruptedException, IOException{RandomAccessFile r = new RandomAccessFile("d://testData.java","rw");FileChannel temp = r.getChannel();FileLock fl = temp.tryLock();System.out.println(fl== null);temp.close();}}
返回的结束是 ture , 也就是得不到文件的锁。
这就是对于进程唯一性问题我的解决思路,通过锁定文件使其再启动时得不到锁文件而无法启动。
- java.net.ServerSocke让java程序只运行一个实例
- 让Java程序只运行一个实例
- 让Java程序只运行一个实例
- 如何让Java程序只运行一个实例
- 让Java程序只运行一个实例(两种方法都好用)
- 让Delphi程序只运行一个实例
- 让程序只运行一个实例
- Python - 让程序只运行一个实例
- 让程序只运行一个实例
- 让MFC程序只运行一个实例
- 如何让程序只运行一个实例
- Qt让程序只运行一个实例
- Java 只运行一个实例
- java 桌面程序 只运行一个实例(单例)
- 让程序只运行一个实例的方法
- 让程序只运行一个实例的方法总结[转]
- 如何让程序只运行一个实例(VC)
- 让程序只运行一个实例的方法总结
- Android network的Type和 phone的signalStrength
- Android中动态更新ListView
- SQL2000 挂起
- 字符串转化为数字
- [转]浅谈C/C++内存泄露及其检测工具
- java.net.ServerSocke让java程序只运行一个实例
- 跋涉之旅之Posix线程编程指南(1)
- mysql的复制技术
- MC3090R设备开发时,引用Symbol.Barcode.dll后组件为灰色的解决方案
- oracle中job的简单实例
- android开发和测试工具分析_DDMS和MAT
- Ubuntu输入su提示认证失败的解决方法
- 精伦IDR200调用ReadBaseInfosPhoto接口问题
- jsp 将html字符串输出html标签