java.net.ServerSocke让java程序只运行一个实例
2012-05-08 15:58
375 查看
问题提出:
一个程序可以在内存里面存在多个运行实例,比如可打开多个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);
}
if(listenerSocketFlagNum==2){
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方法时:
返回的结束是 ture , 也就是得不到文件的锁。
这就是对于进程唯一性问题我的解决思路,通过锁定文件使其再启动时得不到锁文件而无法启动。
一个程序可以在内存里面存在多个运行实例,比如可打开多个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);
}
if(listenerSocketFlagNum==2){
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程序只运行一个实例
- 如何让Java程序只运行一个实例
- 让Java程序只运行一个实例
- 让Java程序只运行一个实例
- java 桌面程序 只运行一个实例(单例)
- Java程序只运行一个实例[转]
- 一个ubuntu下运行java程序的实例
- 使用进程互斥实现WinForm程序只运行一个实例(VB.Net)
- 让Java程序只运行一个实例(两种方法都好用)
- 让你的Java程序只有一个进程实例在运行
- 使用进程互斥实现WinForm程序只运行一个实例(VB.Net)
- Java Swing 每次打开只运行一个实例,并激活任务栏里的程序
- 做完一个小网站的一点经验总结(2):asp.netaccess程序运行环境的配置
- java-用java.net.Socket和java.net.ServerSocket实现简单的聊天程序
- 在VC++中实现让程序只运行一个实例的方法
- ubuntu下运行java程序实例
- JAVA文件锁之保证仅有一个实例运行
- c# 程序只能运行一次(多次运行只能打开同一个程序) 并激活第一个实例,使其获得焦点,并在最前端显示.
- delphi程序只允许运行一个实例的三种方法:(转)
- 解决C#程序只允许运行一个实例的几种方法详解