I'm trying to run an asynchronous process and getting its inputstream (if there is).
This is my code:
CommandCall commandCall = new CommandCall(commands);
ExecutorService executor = Executors.newSingleThreadExecutor();
Future<Integer> task = executor.submit(commandCall);
and this is the process run Task
public class CommandCall implements Callable<Integer> {
private byte[] output;
private int retval=-1;
private String[] commands=null;
Process process=null;
public CommandCall(String[] commands) throws Exception {
this.commands=commands;
this.output=null;
}
public void destroy() {
try {
if(process!=null) process.destroy();
}catch(Exception e){}
}
public byte[] getByteArray() {
return output;
}
public int getRetval() {
return retval;
}
@Override
public Integer call() throws Exception {
try{
process = new ProcessBuilder(commands).start();
// here i must read the process input and store it to this.output
// this must be a non lockable read because the process can be without any output
retval= process.waitFor();
}finally{
try{
if(bos!=null) bos.close();
}catch(Exception e){}
}
return retval;
}
}
I can't get the process output, please mind 2 very important thing:
UPDATE
I'm trying this version... seems to work but I don't know if it is strong enought.
@Override
public Integer call() throws Exception {
InputStream is=null;
try{
process = new ProcessBuilder(commands).start();
is=process.getInputStream();
int len;
int size = 1024;
ByteArrayOutputStream bos = new ByteArrayOutputStream();
byte[] buf = new byte[size];
while ((len = is.read(buf, 0, size)) != -1)
bos.write(buf, 0, len);
output = bos.toByteArray();
retval= process.waitFor();
}finally{
try{
if(is!=null) is.close();
}catch(Exception e){}
}
return retval;
}
The behavior that is observing the process' output should be itself in an own thread. Once the process is terminated, this thread should be terminated, too.
So basically you can do this:
@Override
public Integer call() throws Exception {
Thread outputObserver = null;
try(ByteArrayOutputStream baos = new ByteArrayOutputStream()) {
this.process = new ProcessBuilder(commands).start();
outputObserver = new OutputObserver(process.getInputStream(), baos);
outputObserver.start();
this.retval = process.waitFor();
this.output = baos.toByteArray();
}finally{
if(outputObserver != null) outputObserver.interrupt();
}
return this.retval;
}
private static OutputObserver extends Thread {
private final InputStream input;
private final OutputStream output;
OutputObserver(InputStream input, OutputStream output) {
this.input = input;
this.output = output;
}
@Override
public void run() {
while(!Thread.interrupted()) {
// Copy bytes from input to output here (handling any exceptions).
// Maybe use 3rd party libs for that.
}
// Make sure to copy remaining bytes here, too.
}
}
A couple of notes:
Thread
but rather implement Runnable
. I simply wanted to not over-complicate things.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.