〔Java〕只运行一个实例(使用System.setErr()重定向)
如何只运行一个实例,网上有三种方法(单模式不算):
1、占用端口(有效,但是有端口被挪用的缺陷)
2、检查文件是否存在(有效,但突然停机可能有问题)
3、使用JNI(有效,但丧失可移植性)
我写的和第二个原理差不多,判断某个文件是否被占用,并且我把记录日志、保存日志、判断是否运行放在一起。
你可以转载本Blog,但是不能篡改作者名称。
import java.awt.event.WindowEvent;
import java.awt.event.WindowAdapter;
import java.io.File;
import java.io.IOException;
import java.io.PrintStream;
import java.io.FileOutputStream;
import java.io.FileNotFoundException;
import javax.swing.JFrame;
/*******************************************************************************
*
* 只运行一个实例
*
* Just single instance
*
*
* Author: NeedJava
*
* Modified: 2007.08.29
*
*
* 你可以使用此程序于任何地方,但请保留程序作者及注释的完整。如果你改进了程序,
*
* 请在原作者后添加姓名,如:Author: NeedJava/Jack/Mike,版本及修改时间同理。
*
******************************************************************************/
public final class SingleInstance
{
/*****************************************************************************
*
* 构造函数
*
****************************************************************************/
private SingleInstance()
{
this( "vab", ".vab", "vab" );
}
public SingleInstance( String filePrefixName, String fileSuffixName, String directoryName )
{
this.init( filePrefixName, fileSuffixName, directoryName );
}
/*****************************************************************************
*
* 原理:
*
* 用重定向将标准错误输出流定向到一个日志文件,占用它,使其不能被删除
*
* 以后的实例试图将存在的此日志文件改名并且另存为某个文件夹下
*
* 如果成功,说明没有程序占用它(不排除你在用它,缺陷?),正好保存日志
*
* 如果不成功,退出、renameTo命令有一箭双雕的作用
*
****************************************************************************/
private final void init( String filePrefixName, String fileSuffixName, String directoryName )
{
if( filePrefixName==null||fileSuffixName==null||directoryName==null )
{
exitWithWarning( "Error: Invalid file name.", 10 );
}
//We need check the fileSuffixName here? From the tail?
String fileName=filePrefixName+fileSuffixName;
try{ File error=new File( fileName );
if( error.exists() )
{
File directory=new File( directoryName );
String newFileName=directoryName+File.separator+convertMillisecond2DateTime( error.lastModified() )+fileSuffixName;
//System.out.println( newFileName );
if( directory.exists() )
{
if( directory.isDirectory() )
{
//renameTo也是好东东,既可以改名,还可以移文件
if( !error.renameTo( new File( newFileName ) ) )
{
exitWithWarning( "Error: The instance already exists, I will exit.", 11 );
}
}
else{ exitWithWarning( "Error: The /'"+directoryName+"/' is not a valid directory.", 21 );
}
}
else{ if( directory.mkdirs() )
{
//renameTo也是好东东,既可以改名,还可以移文件
if( !error.renameTo( new File( newFileName ) ) )
{
exitWithWarning( "Error: The instance already exists, I will exit.", 11 );
}
}
else{ exitWithWarning( "Error: Failed to create the /'"+directoryName+"/' directory.", 22 );
}
}
}
//重定向标准错误输出流,所有功能全靠它。
System.setErr( new PrintStream( new FileOutputStream( fileName ) ) );
}
catch( FileNotFoundException fnfe )
{
//fnfe.printStackTrace();
exitWithWarning( fnfe.toString(), 23 );
}
catch( IOException ioe )
{
//ioe.printStackTrace();
exitWithWarning( ioe.toString(), 29 );
}
catch( Exception e )
{
//e.printStackTrace();
exitWithWarning( e.toString(), 99 );
}
}
/*****************************************************************************
*
* You can change the milliseconds to the date and time string here
*
* I just return the original
*
* Don't get the same string :)
*
****************************************************************************/
private final String convertMillisecond2DateTime( long millisecond )
{
return ""+millisecond;
}
/*****************************************************************************
*
* Return the warning and the exit code, then exit the application
*
****************************************************************************/
private final void exitWithWarning( String warning, int code )
{
System.out.println( warning==null ? "" : warning );
System.exit( code );
}
/*****************************************************************************
*
* 主函数入口
*
****************************************************************************/
public final static void main( String[] args )
{
SingleInstance si=new SingleInstance( "error", ".txt", "error" );
final JFrame frame=new JFrame( "Just single instance. By NeedJava. 2007.08.29" );
frame.addWindowListener( new WindowAdapter()
{
public void windowClosing( WindowEvent we )
{
frame.dispose();
System.exit( 0 );
}
} );
frame.setBounds( 200, 200, 700, 70 );
frame.setVisible( true );
}
}
- 使用.bat文件运行Java程序的一个示例
- 反射-实例化一个未知的类(使用System.AppDomain类)
- 使用命名对象来防止运行一个应用程序的多个实例
- 使用命名对象防止运行一个程序的多个实例【转】
- 使用C#实现只允许运行一个程序实例的几种方法
- 使用进程互斥实现WinForm程序只运行一个实例(VB.Net)
- 设置windows2008系统缓存大小限制,解决服务器运行久了因物理内存耗尽出僵死(提升权限后,使用SetSystemFileCacheSize API函数,并将此做成了一个Service)
- Java泛型类实例,使用链表来实现一个堆栈类
- [JAVA]使用Eclipse从下载到编写一个实例全过程
- java 使用线程做的一个简单的ATM存取款实例代码
- JAVA文件锁之保证仅有一个实例运行
- Java实例说明 100个线程同时向一个银行账户中存入1元钱,在没有使用同步机制和使用同步机制情况下的执行情况
- QT单实例应用,使用QLocalSocket进行进程通信,不同运行权限下运行的同一个进程通讯失败,报错 “QLocalSocket::SocketAccessError”
- 让你的Java程序只有一个进程实例在运行
- 反射-实例化一个未知的类(使用System.AppDomain类)
- java JDBC:一个数据库的简单使用实例
- 使用.bat文件运行Java程序的一个示例
- 如何让Java程序只运行一个实例
- Java保证只有一个实例运行,再次启动将激活前一个实例
- 在Sun Java System Web Server上使用Quercus运行PHP