public class ProcessBuilder {
/**
* 进程运行标记文件名称
*/
public final String SIGN_RUN_FILE_NAME = "run.do";
private static Logger log = Logger.getLogger(ProcessBuilder.class);
/**
* 创建进程
*
* @param cmd
* 命令行
* @param workDir
* 指定的工作目录
* @throws IOException
*/
public Process create(String[] cmd, File dir) throws Exception {
// 执行命令行,创建新的进程
Process ps = Runtime.getRuntime().exec(cmd, null, dir);
if (ps != null) {
// (非常重要)输出进程流中的信息,防止运行过程中因为进程流的阻塞,导致被迫挂起
new ProcessStreamUtil(ps.getErrorStream(), "ERROR").start();
new ProcessStreamUtil(ps.getInputStream(), "OUTPUT").start();
return ps;
}
return null;
}
/**
* 标记进程的运行 (注:在运行主目录下创建一个目标文件,并加上文件锁, 用于当外部程通过文件锁来判断程序是否正在运行)
*
* @return
*/
public boolean signRunning() throws Exception {
// 运行目录
String lockPath = System.getProperty("user.dir");
File dir = new File(lockPath);
if (!dir.exists()) {
dir.mkdirs();
}
// 待锁定的目标文件路径
lockPath = lockPath + File.separator + SIGN_RUN_FILE_NAME;
log.debug("标记文件:" + lockPath);
return this.tryLockFile(lockPath);
}
/**
* 通过文件锁来判断程序是否正在运行
*
* @return 如果正在运行返回true,否则返回false
*/
public boolean isRunning(String lockFilePath) throws Exception {
log.debug("嗅探文件:" + lockFilePath);
int i = 0;
// 延时60秒,嗅探目标文件是否已被锁上
do {
if (i++ > 20) {
return false;
}
if (!this.tryLockFile(lockFilePath)) {
return true;
} else {
Thread.sleep(3 * 1000L);
}
} while (true);
}
/**
* 尝试对目标文件进行加锁操作
*
* @param lockFilePath
* 目标文件
* @return
*/
private boolean tryLockFile(String lockFilePath) throws Exception {
// 待锁定的目标文件路径
log.debug(lockFilePath);
RandomAccessFile fis = null;
FileLock flock = null;
FileChannel lockfc = null;
try {
fis = new RandomAccessFile(lockFilePath, "rw");
lockfc = fis.getChannel();
// 尝试加锁
flock = lockfc.tryLock();
if (flock != null) {
return true;
}
} finally {
// 释放资源
if (fis != null)
fis.close();
if (flock != null)
lockfc.close();
}
return false;
}
}
// 进程流输出工具类
public class ProcessStreamUtil extends Thread {
private Logger log = Logger.getLogger(ProcessStreamUtil.class);
private InputStream is = null;
private String type = null;
public ProcessStreamUtil(InputStream is, String type) {
this.is = is;
this.type = type;
}
public void run() {
log.debug(type + "......");
InputStreamReader isr = null;
BufferedReader br = null;
try {
isr = new InputStreamReader(is);
br = new BufferedReader(isr);
String line = null;
while ((line = br.readLine()) != null) {
log.debug(type + ">" + line);
}
} catch (Exception ioe) {
log.error(ioe);
} finally {
try {
if (isr != null)
isr.close();
if (br != null)
br.close();
} catch (Exception er) {
log.error(er);
}
}
}
}
分享到:
相关推荐
Java 程序的编译及运行实验说明 Java 程序的编译及运行是一门编程语言的基础和核心,掌握 Java 程序的编译及运行是每个 Java 开发者必备的技能。本实验的目的是让学生熟悉 Java 编译系统环境,掌握 Java 的 ...
Java字节码程序在Java虚拟机(JVM)上运行,这是Java平台无关性的基础,因为它不需要直接针对特定的硬件平台进行编译。Java程序对硬件平台的依赖性较低,因为JVM在各个平台上都有实现,使得Java程序可以在任何支持...
在Java编程语言中,获取程序运行环境的信息是十分常见的需求,这有助于开发者了解程序的运行状态,调试问题,或者根据不同的环境配置进行条件判断。Java提供了丰富的类库和方法来获取这些信息,主要包括JVM(Java...
在实际项目中,有时我们需要判断一个Quartz任务是否正在运行,以便进行相应的操作,如避免重复执行或者进行状态监控。本文将详细介绍如何在Quartz中实现这一功能。 首先,理解Quartz的工作原理是关键。Quartz通过...
Java U盘检测小程序是一种利用Java编程语言开发的小型应用程序,主要功能是监控并检测接入到计算机的U盘设备。这个程序的设计理念是为了提供一个简单易用的工具,帮助用户了解和管理他们的U盘设备。通过使用线程技术...
用户从键盘输入一个1-9999之间的数,程序将判断这个数是几位数,并判断这个数是否回文数。回文数是指将数含有的数字逆序排列后得到的数和原数相同,例如12121,4224,6778776等都是回文数。 里面的word包含有详细的...
5. **测试.exe文件**:生成后,验证.exe文件是否能正常运行,检查所有依赖是否已包含,程序逻辑是否正确。 需要注意的是,将Java程序转换为.exe文件并不能完全隐藏Java的事实,它仍然是基于Java的,并可能需要特定...
Java程序设计基础 #### 2.1 输入输出操作 Java中输入输出操作通常通过`java.util.Scanner`类来完成,但在给定的代码片段中,作者使用了C++风格的输入输出方式。正确的Java输入输出方式应该使用`Scanner`类。例如:...
在Android应用开发中,判断程序是否为第一次运行是一项常见的需求,通常用于引导用户熟悉应用程序的界面和功能。这个过程可以通过多种方法实现,其中最常用的一种就是利用SharedPreferences存储一个标记值。...
总结来说,Java应用程序类加载器是Java程序执行的关键部分,它负责在运行时找到并加载类,而它的灵活性和可配置性为开发者提供了强大的能力来适应各种复杂的应用场景。理解并掌握类加载器的工作原理,能帮助我们更好...
JDK(Java Development Kit)是开发和运行Java应用程序的基础,包含了编译器、JVM(Java虚拟机)和开发工具。实验要求学生完成JDK的安装,并设置相应的环境变量,确保系统能够找到Java编译器和运行时环境。此外,还...
5. **异常处理**:Java通过异常处理机制来处理程序运行时可能出现的问题。异常是通过`try-catch-finally`块来捕获和处理的。理解如何正确地抛出和捕获异常对于编写健壮的代码至关重要。 6. **输入输出(I/O)**:...
8. **异常处理**:Java的异常处理机制通过try-catch-finally语句来捕获和处理程序运行时可能出现的错误,确保程序的健壮性。 9. **输入/输出流**:Java的IO流库提供了读写文件、网络通信等功能。学习流的概念和使用...
Java运行时监控是Java开发和运维过程中至关重要的一个环节,它可以帮助我们理解应用程序在实际运行中的性能、资源消耗以及可能出现的问题。通过对Java应用的实时监控,我们可以及时发现并解决潜在的性能瓶颈,优化...
这个Java程序的运行流程是: 1. 输出提示“输入年份”并读取用户输入。 2. 检查年份是否在1900年至2010年之间,若不在范围内,则输出错误信息。 3. 判断输入的年份是否为闰年,输出相应的结果。 4. 输出提示“输入...
这个程序可以帮助学习者理解基本的输入输出、条件判断和循环结构。 2. **文字冒险游戏**:这种类型的游戏涉及更复杂的逻辑和数据结构,比如使用字符串、数组或链表来存储地图和角色状态。它可以锻炼程序员的逻辑...
它的设计目标是“一次编写,到处运行”,这意味着编写的Java代码可以在任何支持Java的平台上运行,无需重新编译。Java的语法与C++相似,但更简洁,更安全,因为它避免了指针和内存管理等可能导致错误的特性。 二、...
Java的`FilenameFilter`接口可以实现这一功能,通过自定义实现其`accept()`方法来判断文件是否满足条件。 3. **文件运行**: - 对于Windows系统,文件运行通常涉及到系统命令行调用。在Java中,可以使用`Runtime....