Java 程序只运行一个进程--思路
2014-10-30 17:23
417 查看
写了一个SWT程序 Windows 下运行,由于启动时需要检测 改程序是否已经启动,如已经启动给予提示不再另打开程序。
经搜索:
综合网上各种方案 最终总结4方案:
1.lock File
2.Socket 绑定端口
3.通过JNI 调用 C 程序进行判断。
4.Java6 以上 可以支持 命令行“jps” 命令 可以显示出各个java运行程序的进程ID 和主程序名称或者程序打包的jar报名。
方案特点:
1.方案1简单。
每当程序启动锁定文件,对文件进行标记。再次启动程序读取该文件 发现已被标记,进而不在启动新程序。当程序退出时进行标记清除。
存在致命缺陷: 当程序运行中发生意外退出。没有对文件进行清除标记。将导致程序判断错误。
2.方案2 比方案1 : 可靠,但是这种方案显得 有些 奇怪变通绕行太远,导致其他的问题 局限,
比如 使用的端口被其他程序占用时 或 当有防火墙组织使用端口时 你讲无法绑定端口,程序无法启动。
3.由于 C \C++ 程序可以很好的进行此 判断,因此考虑用C实现 判断方法,让java进行调用。
该方法优点:针对目标直接针对问题解决。 没有绕行,避免绕行带来的其他问题。
该方法缺点:复杂。需要C、C++ 编程经验、
4.方案4 简单 直接。
准备实现: 方案 3 和方案4
实现后我再追加详细代码
【方案4】实现
1.首先找到你要监控成程序名称 :通过 jps 命令
2.验证程序是否已经存在: 通过 包装 Runtime.getRuntime().exec(command); 进行验证
3.程序启动时进行 验证:
事例:中我的程序名称是:AppsHolder.jar
1:打包并运行程序 使程序处于运行状态 使得 jps 命令能捕捉到该程序:
2: 在CMD 中运行 jps命令:
现在:我们从命令行中得到 java 程序名称和进程ID 我们取得 java程序名称AppsHolder.jar
3: 接下来要做的就是通过 java 方法包装 jps 命令 --运行 -- 返回结果 -- 验证是否存在 指定的程序名称 返回 true 或 false:
java Commander 类代码:
至此:我们应经拥有了 根据 传入java程序名称 验证是否 存在应运行有该名称的程序 方法 isApplicationRunning (String appName)
注意: 1. javaTaskApps 方法传入的程序名称和执行执行的命令结果返回,再进行验证前都进行了trim() 和 toLowerCase(); 是为了 忽略大小写和空格
2.isApplicationRunning 方法中进行验证 符合的 程序列表 list.size > 1 而不是大于 0:是因为 当你进行验证的时候 该程序就应经存在在 jps 结果集中,
当大于 1 时才能证明,已经有一个给相同名称的进程已经运行。
最后把该方法添加到程序启动初始位置:
如果验证: 已经有程序启动 将给与提示,并不在打开新 进程。
如果验证: 没有程序已启动 讲启动你的程序:
java 代码:
至此 方案4 已完成:
优点: 1.技术简单
2. 不存在方案1 和方案2 迂回变通带来的严重负面
缺点: 1.需要java6以上 才能支持 jps命令
2.想要跨平台 需要实现 另外平台版本的验证方法。
经搜索:
综合网上各种方案 最终总结4方案:
1.lock File
2.Socket 绑定端口
3.通过JNI 调用 C 程序进行判断。
4.Java6 以上 可以支持 命令行“jps” 命令 可以显示出各个java运行程序的进程ID 和主程序名称或者程序打包的jar报名。
方案特点:
1.方案1简单。
每当程序启动锁定文件,对文件进行标记。再次启动程序读取该文件 发现已被标记,进而不在启动新程序。当程序退出时进行标记清除。
存在致命缺陷: 当程序运行中发生意外退出。没有对文件进行清除标记。将导致程序判断错误。
2.方案2 比方案1 : 可靠,但是这种方案显得 有些 奇怪变通绕行太远,导致其他的问题 局限,
比如 使用的端口被其他程序占用时 或 当有防火墙组织使用端口时 你讲无法绑定端口,程序无法启动。
3.由于 C \C++ 程序可以很好的进行此 判断,因此考虑用C实现 判断方法,让java进行调用。
该方法优点:针对目标直接针对问题解决。 没有绕行,避免绕行带来的其他问题。
该方法缺点:复杂。需要C、C++ 编程经验、
4.方案4 简单 直接。
准备实现: 方案 3 和方案4
实现后我再追加详细代码
【方案4】实现
1.首先找到你要监控成程序名称 :通过 jps 命令
2.验证程序是否已经存在: 通过 包装 Runtime.getRuntime().exec(command); 进行验证
3.程序启动时进行 验证:
事例:中我的程序名称是:AppsHolder.jar
1:打包并运行程序 使程序处于运行状态 使得 jps 命令能捕捉到该程序:
2: 在CMD 中运行 jps命令:
现在:我们从命令行中得到 java 程序名称和进程ID 我们取得 java程序名称AppsHolder.jar
3: 接下来要做的就是通过 java 方法包装 jps 命令 --运行 -- 返回结果 -- 验证是否存在 指定的程序名称 返回 true 或 false:
java Commander 类代码:
/** * 包装 jps命令 * @return * @throws IOException */ public static String jpsCommand() throws IOException { return executeCommand("jps").trim().toLowerCase(); } /** * 包装 Runtime.getRuntime().exec 命令 * @param command 要执行的本地命令 * @return res 返回执行结果 * @throws IOException 运行出现异常 */ public static String executeCommand(String command) throws IOException { Process process = Runtime.getRuntime().exec(command); InputStream inputStream = process.getInputStream(); BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream)); String line = null; StringBuilder tasklist = new StringBuilder(); while ((line = reader.readLine()) != null) { tasklist.append(line + "\n"); } reader.close(); inputStream.close(); String rs = tasklist.toString(); return rs; } /** * 分析 jps 中是符合 传入名称的程序 * @param jar 验证过滤的 java程序名称 * @return List<String> 返回符合的程序名称列表 */ public static List<String> javaTaskApps(String jar) { Set set = new HashSet(); String javaTaskApps = null; try { javaTaskApps = jpsCommand(); } catch (IOException e) { return null; } String reg = ".*"+jar.trim().toLowerCase(); Pattern pattern = Pattern.compile(reg); Matcher matcher = pattern.matcher(javaTaskApps); while (matcher.find()) { set.add(matcher.group()); } List<String> exeList = new Vector<String>(set); return exeList; } /** * 通过本地jps命令验证是否已经有指定的java 程序已经云溪 * @param appName 需要验证的 java 程序名称:该名称是 jps 中能显示的java程序名称 * @return 是否 已经运行 */ public static boolean isApplicationRunning(String appName) { List<String> list = javaTaskApps(appName); if (list != null && list.size() > 1) { return true; } else { return false; } }
至此:我们应经拥有了 根据 传入java程序名称 验证是否 存在应运行有该名称的程序 方法 isApplicationRunning (String appName)
注意: 1. javaTaskApps 方法传入的程序名称和执行执行的命令结果返回,再进行验证前都进行了trim() 和 toLowerCase(); 是为了 忽略大小写和空格
2.isApplicationRunning 方法中进行验证 符合的 程序列表 list.size > 1 而不是大于 0:是因为 当你进行验证的时候 该程序就应经存在在 jps 结果集中,
当大于 1 时才能证明,已经有一个给相同名称的进程已经运行。
最后把该方法添加到程序启动初始位置:
如果验证: 已经有程序启动 将给与提示,并不在打开新 进程。
如果验证: 没有程序已启动 讲启动你的程序:
java 代码:
public static void main(String[] args) { boolean running = Commander.isApplicationRunning("AppsHolder.jar"); // 验证已经启动给予提示 并不在启动新进程 if (running) { MessageBox box = new MessageBox(new Shell(),SWT.ICON_WARNING); box.setText("警告消息"); box.setMessage("有一个程序已经运行!\n请查看状态栏右下角是否有已经打开的程序."); box.open(); } else { //验证失败 说明没有启动过程序 进行程序启动吧 兄弟... ApplicationRunnerUI app = new ApplicationRunnerUI(); app.open();//.... 启动程序 } }
至此 方案4 已完成:
优点: 1.技术简单
2. 不存在方案1 和方案2 迂回变通带来的严重负面
缺点: 1.需要java6以上 才能支持 jps命令
2.想要跨平台 需要实现 另外平台版本的验证方法。
相关文章推荐
- Java 实现程序运行状态监控 之我的思路(守护进程)
- 让你的Java程序只有一个进程实例在运行
- JAVA调用系统命令或可执行程序--返回一个Runtime运行时对象,然后启动另外一个进程来执行命令
- 在同一个进程空间运行两个程序
- 在VC中实现一次执行一个进程,如果同时打开两个,则报该程序已经运行
- 一个简单java小程序打包成EXE运行文件
- 让Java程序只运行一个实例(两种方法都好用)
- 闲的无聊可以运行这个Java程序,添加或减少一个nest loop试一试
- 控制一个 Java 程序运行生命周期结束前不能再次被执行
- Java程序运行结果输出到一个文件中去,结果显示乱码
- vc 防止程序重复运行(即只运行一个实例)并激活已运行进程和枚举进程及窗口
- 使用.bat文件运行Java程序的一个示例
- 使用.bat文件运行Java程序的一个示例
- 让Java程序只运行一个实例
- 在同一个进程空间运行两个程序
- 一个在ksh中运行java程序的例子
- 让一个程序运行一次,在它运行时,不允许再启动一个新的进程。
- 在同一个进程空间运行两个程序
- 一个将java程序运行在linux系统后台的脚本
- ubuntu,显示端口占用,显示正在运行的程序,以及强制关闭一个进程