Java:更改调用线程的变量

时间:2013-09-19 10:26:36

标签: java multithreading

我有以下代码:

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变量。我可能需要某种线程间的通信。我是线程的新手,请告诉我如何做到这一点

3 个答案:

答案 0 :(得分:3)

在您的情况下,表达式this中的this.status引用了没有定义状态字段的Runnable对象。请尝试使用Shell.this.status代替this.status

答案 1 :(得分: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

答案 2 :(得分: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();

  }

}

<强>加

使用Holder的这种解释是解决不同问题的方法 - 即需要从匿名类内部修改最终对象。

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

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