java - Java Unix 脚本执行线程休眠行为
问题描述
我有一个 java web-app 应用程序,它使用 ProcessBuilder 执行本机 unix bash 脚本,我的 unix 脚本在外部资源上有等待和睡眠逻辑。
在某些情况下,应用程序会间歇性挂起,我怀疑 unix 脚本执行可能是其背后的原因之一。
Java 代码示例:
public static void resourceCheck(String arg) throws IOException, InterruptedException {
String[] cmd = { "sh", "/usr/hdf/current/nifi/custom_scripts/resExec.sh",arg};
Process p = Runtime.getRuntime().exec(cmd);
p.waitFor();
BufferedReader reader=new BufferedReader(new InputStreamReader(
p.getInputStream()));
//Get results and log
}
Bash 脚本片段
while [ ! -f ${watcher_file} ]
do
echo -e `date "+%Y-%m-%d %H:%M:%S"`" : Watcher file ${watcher_file} not created yet.\nWaiting for ${wait_timer} seconds" | tee -a "${LOG_FILE}"
sleep ${wait_timer}
done
根据我的经验,我有大量的 java Thread.sleep 而不会影响应用程序,但我不确定 unix 脚本有线程睡眠会发生什么。
您能否解释一下当 Java Process builder 触发具有线程睡眠的 unix 脚本以及这种方法的任何潜在问题时它是如何工作的?
解决方案
您必须在waitFor
读取过程标准输出流之后使用,而不是之前。如果您的应用程序没有正确使用 STDOUT / STDERR 流, Javaexec
调用也可能会挂起,尽管它不清楚您的子进程是否写了很多。如果您切换到 ProcessBuilder 并将 STDERR 合并到 STDOUT ,则更容易解决此问题:
ProcessBuilder pb = new ProcessBuilder(cmd);
pb.redirectErrorStream(true);
Process p = pb.start();
try(var stdout = p.getInputStream()) {
stdout.transferTo(System.out); // or wherever
}
int rc = p.waitFor();
在某些 web 应用程序中使用这种类型的调用(即在调用线程中休眠的东西)不是一个好主意 - 例如,如果这是由 servlet 请求触发并且有多个客户端,您最终可能会收到所有请求在所有线程都在进行基本相同的等待时阻塞 Web 应用程序服务器 - 并且没有线程来处理新连接。
推荐阅读
- google-api - 方法:people.get() 不返回名称
- python - 为什么 kivy 在 apk 打包后给出不同的结果?
- c# - 无法在通用 Windows 应用中的设备上调试
- python - 将 Pandas datetimeindex 的频率从每天更改为每小时,以根据每日重采样数据的条件选择每小时数据
- google-bigquery - BigQuery:超过对列分区表的分区修改次数的配额
- javascript - 如何在 jquery for 循环中使用字符串替换?
- java - 实现必须从不同线程添加/删除元素的元素列表的最佳方法是什么?
- python - 没有参数的 Pytest 有错误的工作目录
- python - 无法在 jupyter 笔记本中导入 rmagic
- c++11 - 包括自身在内的 C++ 文件