针对Javaprocess.waitFor和从不返回这两个问题,本篇文章进行了详细的解答,同时本文还将给你拓展Executionfailedfortask'':app:processDebugReso
针对Java process.waitFor和从不返回这两个问题,本篇文章进行了详细的解答,同时本文还将给你拓展Execution failed for task '':app:processDebugResources''. No slave process to process jobs, aborting、FFmpeg在JAVA中的使用以及Process.waitFor()引发的阻塞问题、Flux waitFor()和异步操作,如何建模、Flux waitFor()和异步操作,如何建模。等相关知识,希望可以帮助到你。
本文目录一览:- Java process.waitFor()从不返回(java process.waitfor返回值)
- Execution failed for task '':app:processDebugResources''. No slave process to process jobs, aborting
- FFmpeg在JAVA中的使用以及Process.waitFor()引发的阻塞问题
- Flux waitFor()和异步操作,如何建模
- Flux waitFor()和异步操作,如何建模。
Java process.waitFor()从不返回(java process.waitfor返回值)
Process process = Runtime.getRuntime().exec("tasklist");BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream()));process.waitFor();
答案1
小编典典有很多原因waitFor()
不回来。
但这通常归结为以下事实:执行的命令不会退出。
同样,这可能有很多原因。
一个普遍的原因是该过程产生了一些输出,而你没有从适当的流中读取。这意味着一旦缓冲区已满,进程就会被阻塞,并等待你的进程继续读取。你的进程依次等待另一个进程完成(之所以不会,是因为它等待你的进程,…)。这是一个典型的僵局情况。
你需要不断从流程输入流中读取内容,以确保它不会被阻塞。
Execution failed for task '':app:processDebugResources''. No slave process to process jobs, aborting
今天写项目遇到这个问题:
Execution failed for task '':app:processDebugResources''. No slave process to process jobs, aborting
解决办法:
clean和rebuild如果都没有成功,直接点击 File>Invalidate Caches/Restart后编译,重新打开studio就好
FFmpeg在JAVA中的使用以及Process.waitFor()引发的阻塞问题
此文已由作者叶海啸授权网易云社区发布。
欢迎访问网易云社区,了解更多网易技术产品运营经验。
FFmpeg是一个开源免费跨平台的视频和音频流方案,可以快速对音视频流进行多方面的处理,本文主要介绍FFmpeg常用的命令与参数讲解,如何在JAVA中使用FFmpeg以及遇到的一些问题。
背景
项目需求中涉及到有关于视频、音频的一系列处理,包含视频中音频提取、视频首帧提取、音频重采样、字幕压缩的功能,一直在研究ffmpeg,仅仅几个功能,却深受ffmpeg的折磨。
今天谈谈ffmpeg在java中的简单使用,首先下载ffmpeg包,官方地址:http://ffmpeg.org/download.html, 这里建议下载Linux Static Builds版本的,轻小而且解压后可以直接使用,本人使用的版本是ffmpeg-git-20170922-64bit-static.tar.xz。
解压之后,文件夹中有一个可执行文件ffmpeg,在linux上可以直接运行./ffmpeg -version,可以查看ffmpeg的版本信息,以及configuration配置信息。
基本命令
视频中音频提取:ffmpeg -i [videofile] -vn -acodec copy [targetaudiofile]
视频首帧提取:ffmpeg -i [videofile] -vframes 1 -q:v 2 -f image2 [imagefile]
音频重采样:ffmpeg -i [audiofile] -ar [samplingrate] [targetaudiofile]
字幕压缩:ffmpeg -i [videofile] -vf subtitles=[subtitle.srt] [targetvideofile]
命令说明
audiofile、videofile是音视频源文件,可以是本地文件,也可以是网络文件URL;
提取音频流时,-vn 忽略视频流 -acodec 设定声音编解码器,未设定时则使用与输入流相同的编解码器,如果需要提取视频流,则参数变为-an -vcodec;
-vframes 表示提取的第几帧,获取第一桢则后面的值为1,如果后面的值大于1,那么最后的[imagefile]不能指定一个文件,不然会报错,如下
指定了输出的文件名为“1.jpeg”,报错:不能从1.jpeg文件中获取第二帧的文件名,因为-vframes只要大于1,则会提取出每一帧的图片,建议使用如%03d.jpeg来作为文件名,那么它解析的结果便是001.jpeg,002.jpeg,...依次编号往后;
-q:v 2 q代表质量quality, v代表视频流,2是控制质量的参数;-f指定输出的格式是image2;
除了使用-vframes来获取视频帧,还有使用-ss参数来获取,-ss后的时间参数是自行设定,并且在视频的有效时间内(格式为00:00:00),使用-ss时,如果没有使用%03d.jpeg来作为文件名,则获取的是-ss参数指定的那个时间的帧;
-ar表示使用新的采样率,常用的有8,000Hz、16,000Hz、22,050Hz、32,000Hz、44,100Hz;
subtitle.srt是字幕文件(中文字幕即把英文变为中文,其它格式一致),这边就使用最简单的srt标准格式,srt文件写入的字符编码需要是UTF-8,否则压缩的时候会报无法读取srt文件;
若想压缩中文字幕,需要系统中有中文字体,使用fc-list查询系统支持的字体,fc-list :lang=zh查询支持的中文字体
JAVA使用遇到的问题
一般需要调用系统命令时,大部分人第一反应肯定是使用Runtime.getRuntime().exec(command)返回一个process对象,再调用process.waitFor()来等待命令执行结束,获取执行结果。
产品刚上线,运行很稳定,但是没过多久,产品同学说从某个时间点开始添加的视频都不出来了!因为这个视频必须要经过一系列的处理,才会展示出来,所以中途某个环节出错了。
首先查看了日志,没有发现任何的报错,但是幸好开发的时候加了debug日志,每一句命令exec前后都会打一句log,于是看下是否“开始执行”和“执行成功”两句log都打印了,结果发现在截取首帧的时候,只打印了“开始执行”,一直没有结束,那么猜测进程堵塞了。
但是,我把产品同学的视频拿过来,直接执行提取视频第一帧的命令,提示图片未提取成功,后来发现该视频是产品同学通过某个压缩工具压缩过的,点开视频可以看见黑屏,看不到任何东西,肯定是压缩时把视频压缩出错了,但是截取首帧命令既然执行结束了,按道理不应该一直堵塞啊?
于是通过dump下了内存镜像文件,命令jmap -dump:live,format=b,file=heap.dmp PID,通过jvisualvm工具查看,发现有很多如下的堆栈:
因此可以判断,确实是在截取首帧的时候,进程阻塞了,但是为什么会阻塞???
解决方案
查看waitFor()源码可以发现,其实调用的是Object类中的,wait()方法,并且未指定等待时间,那么如果一直不返回,则会一直阻塞。
并且查看了JDK的帮助文档,如下
因此,可以得出结论:如果外部程序不断在向标准输出流(对于jvm来说就是输入流)和标准错误流写数据,而JVM不读取的话,当缓冲区满之后将无法继续写入数据,最终造成阻塞在waitFor()这里。
解决方法:在waitFor()之前,利用单独两个线程,分别处理process的getInputStream()和getErrorSteam(),防止缓冲区被撑满,导致阻塞;
/**
* 处理process输出流和错误流,防止进程阻塞
* 在process.waitFor();前调用
* @param process
*/
private static void dealStream(Process process) {
if (process == null) {
return;
}
// 处理InputStream的线程
new Thread() {
@Override
public void run() {
BufferedReader in = new BufferedReader(new InputStreamReader(process.getInputStream()));
String line = null;
try {
while ((line = in.readLine()) != null) {
logger.info("output: " + line);
}
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
in.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}.start();
// 处理ErrorStream的线程
new Thread() {
@Override
public void run() {
BufferedReader err = new BufferedReader(new InputStreamReader(process.getErrorStream()));
String line = null;
try {
while ((line = err.readLine()) != null) {
logger.info("err: " + line);
}
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
err.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}.start();
}
免费体验云安全(易盾)内容安全、验证码等服务
更多网易技术、产品、运营经验分享请点击。
相关文章:
【推荐】 Kubernetes 在网易云中的落地优化实践
【推荐】 寓教于乐——玩转角色互换游戏
Flux waitFor()和异步操作,如何建模
我正在将pouchDB用作应用程序的本地数据库。我想从PouchDB查询结果并将其加载到React.js中。但是,即使我使用waitFor()方法,PouchDB查询的结果返回也为时已晚。我认为我不正确地使用waitFor(),也许有人可以对此有所了解。
我有两个商店,即DbStore,它从datbase检索数据。我的react组件使用了这个存储的FileExplorerStore。
DbStore.dispatchToken = AppDispatcher.register(function (payload) {
var action = payload.action;
var folder = payload.action.folder
switch (action.type) {
case 'OPEN_FOLDER':
if (folder === 'start') {
DbStore.init();
}
else {
DbStore.createPath(folder);
}
DbStore.emitChange();
break;
default:
// do nothing
}
return true;
});
DbStore具有函数LoadFiles,它将DB文件加载到_files数组中。为了说明目的,我复制了以下代码:
loadFiles: function (_path) {
var fileNames = fs.readdirSync(_path);
_files = [];
fileNames.forEach(function (file) {
console.log(file)
db.query(function (doc) {
emit(doc.name);
},{key: "bower.json"}).then(function (res) {
_files.push(res.rows[0].key)
});
});
},
FileExplorerStore具有一种从_files数组检索文件的方法。然后在FileExplorerStore中,我有一个getFiles()方法,它将检索这些文件。但是,此数组始终为空,因为将在填充数组之前执行此方法。
FileExplorerStore
FileExplorerStore.dispatchToken = AppDispatcher.register(function (payload) {
var action = payload.action;
switch (action.type) {
case 'OPEN_FOLDER':
AppDispatcher.waitFor([DbStore.dispatchToken]);
FileExplorerStore.emitChange();
break;
default:
// do nothing
}
return true;
});
在react.js中,getInitialState函数将从FileExplorerStore调用getFiles()函数以显示文件。
如何解决此问题或以更好的方式对此建模?
Flux waitFor()和异步操作,如何建模。
我正在将pouchDB用作应用程序的本地数据库。我想从PouchDB查询结果并将其加载到React.js中。但是,即使我使用waitFor()方法,PouchDB查询的结果返回也为时已晚。我认为我不正确地使用waitFor(),也许有人可以对此有所了解。
我有两个商店,即DbStore,它从datbase检索数据。我的react组件使用了这个存储的FileExplorerStore。
DbStore.dispatchToken = AppDispatcher.register(function (payload) { var action = payload.action; var folder = payload.action.folder switch (action.type) { case ''OPEN_FOLDER'': if (folder === ''start'') { DbStore.init(); } else { DbStore.createPath(folder); } DbStore.emitChange(); break; default: // do nothing } return true;});
DbStore具有函数LoadFiles,它将DB文件加载到_files数组中。为了说明目的,我复制了以下代码:
loadFiles: function (_path) { var fileNames = fs.readdirSync(_path); _files = []; fileNames.forEach(function (file) { console.log(file) db.query(function (doc) { emit(doc.name); }, {key: "bower.json"}).then(function (res) { _files.push(res.rows[0].key) }); }); },
FileExplorerStore具有一种从_files数组检索文件的方法。然后在FileExplorerStore中,我有一个getFiles()方法,它将检索这些文件。但是,此数组始终为空,因为将在填充数组之前执行此方法。
FileExplorerStore
FileExplorerStore.dispatchToken = AppDispatcher.register(function (payload) {var action = payload.action;switch (action.type) { case ''OPEN_FOLDER'': AppDispatcher.waitFor([DbStore.dispatchToken]); FileExplorerStore.emitChange(); break; default: // do nothing}return true;});
在react.js中,getInitialState函数将从FileExplorerStore调用getFiles()函数以显示文件。
如何解决此问题或以更好的方式对此建模?
答案1
小编典典该waitFor
在dispatcher
通过Facebook的团队发布没有设计为(至少在2014年9月11日发布),它只是确保dispatchToken
(其中传递到waitFor
)被执行并返回,然后就会开始执行下一个注册的回调。
因此,就您而言,这是正确的预期行为。
我要做的是将动作分为两部分。首先是获取,其次是OPEN_FOLDER
中FileExplorerStore
。假设命名的dbfetch行动DB_FETCH
,这将触发你的数据库,然后将数据进入_files
,在获取成功的回调,引发action
的OPEN_FOLDER
。对于触发点,这取决于您要如何设计,我将命名为第三个动作INIT_OPEN_FOLDER
来触发DB_FETCH,然后将加载指示符显示到UI,最后在从获取发射时OPEN_FOLDER
,仅显示数据
关于Java process.waitFor和从不返回的介绍现已完结,谢谢您的耐心阅读,如果想了解更多关于Execution failed for task '':app:processDebugResources''. No slave process to process jobs, aborting、FFmpeg在JAVA中的使用以及Process.waitFor()引发的阻塞问题、Flux waitFor()和异步操作,如何建模、Flux waitFor()和异步操作,如何建模。的相关知识,请在本站寻找。
本文标签: