防止JAVA程序重复启动进程的解决办法

问题:【备注:发现java的NIO是平台相关的,目前只能在Windows上面实现文件锁,而Linux是不支持的。我正在寻找更好的解决办法,有解决方案的朋友,可以在这里留言。谢谢】

【备注:今天在网上找了一个开源的,防止程序启动多进程的jar包。地址: http://www.sauronsoftware.it/projects/junique/manual.php

用起来,很不错。我看了源码,也是nio的文件锁和Socket绑定端口号实现的。不过,他为了防止文件锁不起作用,下面接着用了socket占用端口号,来了一个双重保险。我也懒的自己写了,就用了他的。】

【目前没有好的办法。只能用占用端口号的解决方案】

以前一直在做WEB开发,对于后台程序不是很了解。现在做后台的部分系统开发,发现一个问题:java程序打成jar包之后进行运行,有时候因为人为的原因,会多次启动该jar运行程序。很多情况下,这是不允许的。为了解决java程序被启动多个进程,我找了一些资料,里面说的五花八门。有的说用数据库,有的说用文件写入一个标识。这些方法都可以防止程序被多次启动,但是存在一个很大的问题:如果程序的进程是被 kill 掉的,那么再次启动程序,就会发生问题,因为标志位没有被清空。所以这不是彻底解决问题的方法。

又开始找了一些资料,终于发现了不错的方案。下面给我现在使用的方案,利用Java NIO的文件锁(File Lock)来实现的。还有朋友用的是占用一个不经常用的端口,来实现,这也是一个不错的解决方案。占用端口号的方案,我在这里给出链接: http://sheng.iteye.com/blog/37732

这里是我写的文件锁的解决方案:

 

 

 

package com.concurrency.chapter1;

import java.io.File;
import java.io.FileWriter;
import java.io.RandomAccessFile;
import java.nio.channels.FileChannel;
import java.nio.channels.FileLock;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;

import org.apache.log4j.Logger;

/**
 * <pre>
 * with java NIO file lock to prevent starting more than on process
 * @author kanpiaoxue
 * @date 2012-02-02
 * </pre>
 */
public class SingletonProgram {
	private static Logger logger = Logger.getLogger(SingletonProgram.class);
	private static final String PROGRAMA_NAME = "Singleton";

	/**
	 * @param args
	 */
	public static void main(String[] args) {
		String startMessage = "start " + PROGRAMA_NAME + " application";
		logger.info(startMessage);

		lockSingletonProgramFile(PROGRAMA_NAME);

		try {// simulate running program
			ExecutorService exec = Executors.newSingleThreadExecutor();
			exec.execute(new Runnable() {

				@Override
				public void run() {
					logger.info("start to run test thread.");
					while (true) {

						try {
							long sleepTime = 10L;
							logger.info("run test thread successfully. It will sleep "
									+ sleepTime + " seconds");
							TimeUnit.SECONDS.sleep(sleepTime);
						} catch (InterruptedException e) {
							e.printStackTrace();
						}
					}
				}
			});
			exec.shutdown();
		} catch (Exception ex) {
			ex.printStackTrace();
		}
		logger.info(startMessage + " successfully!");
	}

	/**
	 * method destination : privent starting more than one program process in
	 * system processes
	 * 
	 * @param programName
	 */
	private static void lockSingletonProgramFile(String programName) {
		// java -DlockFile=D:\lock\tmplock\application.lock -jar
		// SingletonProgram.jar

		final String startFailureMessage = "Error:start " + programName
				+ " application";
		String lockFile = System.getProperty("lockFile");
		logger.info("start " + programName + " application with [lockFile] : "
				+ lockFile);
		if (null == lockFile) {
			lockFile = System.getProperty("user.dir") + File.separator
					+ programName + ".lock";
			logger.warn("does not provide lockFile, it will use default lockFile which is ["
					+ lockFile + "]");
		}
		RandomAccessFile raf = null;
		FileChannel fileChannel = null;
		FileLock flock = null;
		FileWriter writer = null;
		try {
			File file = new File(lockFile);
			if (!file.exists()) {
				String parent = file.getParent();
				File folder = new File(parent);
				if (!folder.exists() || !folder.isDirectory()) {
					if (!folder.mkdirs()) {
						logger.error(startFailureMessage
								+ " failure: create lock file folder failure:"
								+ parent);
						System.exit(-1);
					}
				}
				if (!file.createNewFile()) {
					logger.error(startFailureMessage
							+ " failure: create lock file failure:" + lockFile);
					System.exit(-1);
				}
			}
			writer = new FileWriter(file);
			writer.write(programName);
			/**
			 * Here,we force flush data into lock file. If there already has a
			 * process in system processes, it will catch Exception.
			 */
			writer.flush();
			writer.close();
			raf = new RandomAccessFile(file, "rw");
			fileChannel = raf.getChannel();
			flock = fileChannel.tryLock();// start to try locking lock file
			/**
			 * <pre>
			 * Note: 
			 * Here, at first time, you cann't release or close these resources.
			 * If you do it, you will find that it cann't prevent more than one program process
			 * running in system processes.
			 * </pre>
			 */
		} catch (Exception e) {
			logger.error(startFailureMessage + " failure: lock file is ["
					+ lockFile + "]:" + e.getMessage(), e);
			try {
				/**
				 * <pre>
				 * Note:
				 * If you start program process failure, 
				 * you need to try releasing and closing these resources.
				 * </pre>
				 */
				if (null != writer) {
					writer.close();
				}
				if (null != flock) {
					flock.release();
				}
				if (null != fileChannel) {
					fileChannel.close();
				}
				if (null != raf) {
					raf.close();
				}
			} catch (Exception ex) {
				logger.error(
						"Error: close resource failure:" + ex.getMessage(), ex);
			}
			logger.error("There is a "
					+ programName
					+ " application process in system processes. Now exit starting!");
			System.exit(-1);
		}
	}

}

 

 

你可能感兴趣的:(java)