1

我有以下代码,但是当我在新的 Thread 类之外声明 String 行时,我得到了一个异常。我来自 C# 背景,所以我现在明白 Java 不支持真正的闭包。所以我的问题是:

如何在新线程之外声明一个字符串并在新线程中使用它?

无法引用以不同方法定义的内部类中的非最终变量行

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();
4

4 回答 4

3

更改line为 aStringBuilder并将其声明为final. 然后将run()方法更改为追加到StringBuilder.

如果您join()在尝试读取line主线程之​​前是子线程,则不需要使用StringBuffer.

于 2013-04-07T15:34:17.237 回答
1

你必须:

  1. 创建一个专门用于读取 Process 输出的新类(实现Future
  2. 在将其结果与ExecutorService方法一起使用之前,等待其类的实例(作业)。

这是一个代码示例:

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();
   }
}

result.get()如有必要,调用者的阻塞等待由 内部进行。

于 2013-04-07T15:51:22.247 回答
0

您应该创建另一个对象来保存和更改String. 将此对象设为最终对象并使用此对象方法更改字符串。

您可以尝试使用StringBuilder作为最终对象并使用其append功能来修改字符串。

于 2013-04-07T15:31:11.603 回答
0

或者,line在内部类中声明为实例变量,因为无论如何您都没有在类外部使用它:

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();
于 2013-04-07T18:05:21.213 回答