2

我有以下代码:

public class Shell {
  String status;
  Runtime rtime;
  Process process;

  public void runCmd(final String cmd,String status) throws Exception{
     this.status = status;
     Thread t = new Thread(new Runnable() {
           @Override
           public void run() {
              try {
                 process = rtime.exec(cmd);
                 process.waitFor();
                 this.status = "check out done";
             } catch (IOException e) {

             } catch (InterruptedException e) {

             }
          }
    });

    t.start();

  }

}

但是java不允许我更改status新线程t内的变量。可能是我需要某种线程间通信。我是线程新手,请告诉我该怎么做。

4

3 回答 3

3

在您的情况下this,表达式this.status是指未定义状态字段的 Runnable 对象。尝试Shell.this.status代替this.status.

于 2013-09-19T10:29:41.830 回答
1

问题是您不能从匿名类中的父类访问变量,除非它是最终的,即使它很复杂。当您想修改它时,我建议您这样做:

public class Holder <T> {
  private T held = null;

  public Holder () {
  }

  public Holder (T it) {
    held = it;
  }

  public void hold(T it) {
    held = it;
  }

  public T held() {
    return held;
  }

  @Override
  public String toString () {
    return held == null ? "null": held.toString();
  }
}

然后您的代码可能如下所示:

public class Shell {
  final Holder<String> status = new Holder<>();
  Runtime rtime;
  Process process;

  public void runCmd(final String cmd, String status) throws Exception {
    // Set the status.
    Shell.this.status.hold(status);
    Thread t = new Thread(new Runnable() {
      @Override
      public void run() {
        try {
          process = rtime.exec(cmd);
          process.waitFor();
          Shell.this.status.hold("check out done");
        } catch ( IOException | InterruptedException e) {
        }
      }

    });

    t.start();

  }

}

添加

这种使用 a 的演示Holder解决了一个不同的问题——即需要从匿名类内部修改最终对象。

这个答案不是OP问题的解决方案,如果可以的话,我会删除它。不幸的是,它已被标记为答案,所以我不能。

如果 OP 可以将其他帖子之一标记为正确答案,我很乐意删除它。

于 2013-09-19T10:42:41.763 回答
1
public class Shell {
    volatile String status;

    public void runCmd(final String cmd) throws Exception{
        Thread t = new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    Process process = Runtime.getRuntime().exec(cmd);
                    process.waitFor();
                    Shell.this.status = "check out done";
                } catch (IOException e) {

                } catch (InterruptedException e) {

                }
            }
        });

        t.start();
        t.join();
        System.out.println(status);

    }
}

使用Shell.this.status并将值更新为想要的值。

线程安全

volatile当引用从另一个线程更新时始终使用。

于 2013-09-19T10:40:04.643 回答