I have the following code, but when I declare the String line outside of the new Thread class I get an exception. I'm from a C# background, so I understand now that Java does not support true closures. So my question is:
How can I declare a string outside of new Thread and use it in new Thread?
Cannot refer to a non-final variable line inside an inner class defined in a different method
ProcessBuilder builder =
new ProcessBuilder("/Users/Joe/Desktop/file", "-i", src);
builder.redirectErrorStream(true);
Process process = builder.start();
final InputStream is = process.getInputStream();
String line;
new Thread(new Runnable() {
@Override public void run() {
try {
BufferedReader br = new BufferedReader(new InputStreamReader(is));
while ((br.readLine()) != null) {
line += br.readLine() + "\n";
}
} catch (IOException e) {
e.printStackTrace();
}
}
}).start();
Change line
to be a StringBuilder
and declare it as final
. Then change the run()
method to append to the StringBuilder
.
Provided that you join()
the child thread before you attempt to read line
in the main thread, you don't need to use a StringBuffer
.
You have to:
Here is a code sample:
import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
public class FutureJob {
static class StreamToString implements Callable< String > {
BufferedReader br;
public StreamToString( InputStream in ) {
br = new BufferedReader( new InputStreamReader( in ));
}
@Override public String call() throws Exception {
StringBuilder buffer = new StringBuilder( 1024 );
String line;
while(( line = br.readLine()) != null ) {
buffer.append( line );
buffer.append( '\n' );
}
br.close();
return buffer.toString();
}
}
public static void main( String[] args ) throws Exception {
ProcessBuilder builder = new ProcessBuilder( "cmd", "/C", "dir", "c:\\" );
Process process = builder.start();
ExecutorService executor = Executors.newSingleThreadExecutor();
StreamToString toString = new StreamToString( process.getInputStream());
Future< String > result = executor.submit( toString );
System.out.println( result.get());
executor.shutdownNow();
}
}
The blocking wait of the caller is made internally by result.get()
, if necessary.
You should create another object which will hold and change the String
. Make this object final and change the string using this object method.
You can try using StringBuilder
as the final object and use its append
function to modify the string.
Alternately, declare line
as an instance variable inside the inner class, since you are not using it outside of the class anyway:
new Thread(new Runnable() {
String line;
@Override public void run() {
try {
BufferedReader br = new BufferedReader(new InputStreamReader(is));
while ((br.readLine()) != null) {
line += br.readLine() + "\n";
}
} catch (IOException e) {
e.printStackTrace();
}
}
}).start();
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.