在编写Java程序时,有时候我们需要调用其他的诸如exe,shell这样的程序或脚本。在Java中提供了两种方法来启动其他程序:
(1) 使用Runtime的exec()方法
(2) 使用ProcessBuilder的start()方法
Runtime和ProcessBulider提供了不同的方式来启动程序,设置启动参数、环境变量和工作目录。但是这两种方法都会返回一个用于管理操作系统进程的Process对象。这个对象中的waitFor()是我们今天要讨论的重点。
来说说我遇到的实际情况:我想调用ffmpeg程序来对一首歌曲进行转码,把高音质版本的歌曲转为多种低码率的文件。但是在转码完成之后需要做以下操作:读取文件大小,写入ID3信息等。这时我们就想等转码操作完成之后我们可以知道。
如下这样代码
Process p = null;
try {
p = Runtime.getRuntime().exec("notepad.exe");
} catch (Exception e) {
e.printStackTrace();
}
System.out.println("我想被打印...");
在notepad.exe被执行的同时,打印也发生了,但是我们想要的是任务完成之后它才被打印。
之后发现在Process类中有一个waitFor()方法可以实现。如下:
Process p = null;
try {
p = Runtime.getRuntime().exec("notepad.exe");
p.waitFor();
} catch (Exception e) {
e.printStackTrace();
}
System.out.println("我想被打印...");
这下又出现了这样的现象,必须要等我们把记事本关闭, 打印语句才会被执行。并且你不能手动关闭它那程序就一直不动,程序貌似挂了.....这是什么情况,想调用个别的程序有这么难吗?让我们来看看waitFor()的说明:
JDK帮助文档上这么说:如有必要,一直要等到由该 Process 对象表示的进程已经终止。如果已终止该子进程,此方法立即返回。但是直接调用这个方法会导致当前线程阻塞,直到退出子进程。对此JDK文档上还有如此解释:因为本地的系统对标准输入和输出所提供的缓冲池有效,所以错误的对标准输出快速的写入何从标准输入快速的读入都有可能造成子进程的所,甚至死锁。好了,
问题的关键在缓冲区这个地方:可执行程序的标准输出比较多,而运行窗口的标准缓冲区不够大,所以发生阻塞。
接着来分析缓冲区,哪来的这个东西,当Runtime对象调用exec(cmd)后,JVM会启动一个子进程,该进程会与JVM进程建立三个管道连接:标准输入,标准输出和标准错误流。
假设该程序不断在向标准输出流和标准错误流写数据,而JVM不读取的话,当缓冲区满之后将无法继续写入数据,最终造成阻塞在waitfor()这里。 知道问题所在,我们解决问题就好办了。查看网上说的方法多数是开两个线程在waitfor()命令之前读出窗口的标准输出缓冲区和标准错误流的内容。代码如下:
Runtime rt = Runtime.getRuntime();
String command = "cmd /c ffmpeg -loglevel quiet -i "+srcpath+" -ab "+bitrate+"k -acodec libmp3lame "+desfile;
try {
p = rt.exec(command ,null,new File("C:\\ffmpeg-git-670229e-win32-static\\bin"));
//获取进程的标准输入流
final InputStream is1 = p.getInputStream();
//获取进城的错误流
final InputStream is2 = p.getErrorStream();
//启动两个线程,一个线程负责读标准输出流,另一个负责读标准错误流
new Thread() {
public void run() {
BufferedReader br1 = new BufferedReader(new InputStreamReader(is1));
try {
String line1 = null;
while ((line1 = br1.readLine()) != null) {
if (line1 != null){}
}
} catch (IOException e) {
e.printStackTrace();
}
finally{
try {
is1.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}.start();
new Thread() {
public void run() {
BufferedReader br2 = new BufferedReader(new InputStreamReader(is2));
try {
String line2 = null ;
while ((line2 = br2.readLine()) != null ) {
if (line2 != null){}
}
} catch (IOException e) {
e.printStackTrace();
}
finally{
try {
is2.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}.start();
p.waitFor();
p.destroy();
System.out.println("我想被打印...");
} catch (Exception e) {
try{
p.getErrorStream().close();
p.getInputStream().close();
p.getOutputStream().close();
}
catch(Exception ee){}
}
}
到这里问题的原因也清楚了,问题也被解决了,是不是就结束了。让我们回过头来再分析一下,问题的关键是处在输入流缓冲区那个地方,子进程的产生的输出流没有被JVM及时的读取最后缓冲区满了就卡住了。如果我们能够不让子进程向输入流写入数据,是不是可以解决这个问题。对于这个想法直接去ffmpeg官网查找,最终发现真的可以关闭子进程向窗口写入数据。命令如下:
ffmpeg.exe -loglevel quiet -i 1.mp3 -ab 16k -ar 22050 -acodec libmp3lame r.mp3
稍微分析一下:-acodec 音频流编码方式 -ab 音频流码率(默认是同源文件码率,也需要视codec而定) -ar 音频流采样率(大多数情况下使用44100和48000,分别对应PAL制式和NTSC制式,根据需要选择),重点就是-loglevel quiet这句
http://www.ffmpeg.com.cn/index.php/Ffmpeg%E9%80%89%E9%A1%B9%E8%AF%A6%E8%A7%A3
分享到:
相关推荐
JAVA Process 使用JAVA Process 使用JAVA Process 使用JAVA Process 使用JAVA Process 使用JAVA Process 使用
ProcessMonitor 线程查看工具
windows下只能查看进程的cpu占用率,要查看线程的cpu占用率要借助该工具,线程信息一目了然。
java编写的一个多线程程序,模拟银行排队.-prepared in a multithreaded process that simulates the bank queue.
实现内存动态分区,运用Java语言,一共四个类,这是process类
java imageProcess 图像处理程序模板,java imageProcess 图像处理程序模板
在 Java 语言中,对进程和线程的封装,分别提供了 Process 和 Thread 相关的一些类。本文首先简单的介绍如何使用这些类来创建进程和线程,然后着重介绍这些类是如何和操作系统本地进程线程相对应的,给出了 Java ...
内容简介:线程与进程相似,是一段完成某个特定...所以系统在产生一个线程,或者在各个线程之间切换时,负担要比进程小的多,正因如此,线程被称为轻负荷进程(light-weight process)。一个进程中可以包含多个线程。
实现Java通过进程名称杀进程,列子中主要实现在windows操作系统中,将进程名称为java-test.exe的进程kill掉。
jni win32 sdk java 任务管理器
JAVA语言实现对图像进程的控制和操作,内含25个文件
可以查看并挂起不必要的线程,让你能够更加有效地发现线程与系统中的冲突,更加有效地优化系统
绍Java Process命令
并行计算 多线程 actor 协程 process
JSF是由Java Community Process (JCP)制定的一个Web应用框架标准。JSF具有良好定义的请求处理生命周期和丰富的组件层次结构,旨在推动基于Java的Web用户界面开发的简易性。利用JSF提供的可重用、可扩展、基于组件的...
NULL 博文链接:https://sghfofo.iteye.com/blog/571105
主要介绍了Java Process详解及实例的相关资料,需要的朋友可以参考下
线程(thread),有时被称为轻量级进程(Lightweight Process,LWP),是程序执行流的最小单元。一个标准的线程由线程ID,当前指令指针(PC),寄存器集合和堆栈组成。另外,线程是进程中的一个实体,是被系统独立调度和...
一个能实现类似超线程功能的软件Process Tamer,电脑防死机专家,能让CPU拥有超线程能力的软件。 超线程技术让Intel处理器获得性能提升,同时让CPU工作效率更快。但是只有部分Intel用户才能享受这一功能,对于AMD...
使用PROCESS v3.3 for SPSS,测量中介变量。使用PROCESS v3.3 for SPSS,测量中介变量。