vishesh
vishesh

Reputation: 2045

Java: changing variable of calling thread

I have the following code:

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

  }

}

but java doesn't let me change the status variable inside the new thread t.May be I need some sort of inter thread communication.I am new to threads,please tell me how to do this.

Upvotes: 2

Views: 514

Answers (3)

OldCurmudgeon
OldCurmudgeon

Reputation: 65813

The problem is that you cannot access a variable from a parent class in an anonymous class unless it is final and even then it is complex. As you want to modify it I would suggest something like:

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

Then your code can look like this:

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

  }

}

Added

This demopnstration of the use of a Holder is the solution to a different problem - i.e. the need to modify a final object from inside an anonymous class.

This answer is not the solution to OP's problem and I would delete it if I could. Unfortunately it has been marked as the answer so I cannot.

If OP could mark one of the other posts as the correct answer I would be happy to delete this.

Upvotes: 1

Narendra Pathai
Narendra Pathai

Reputation: 41935

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

    }
}

Use Shell.this.status and update the value to what to want.

Thread Safety

Always use volatile when reference is updated from another thread.

Upvotes: 1

efan
efan

Reputation: 968

In your case this in expression this.status refers Runnable object which does not have status field defined. Try Shell.this.status instead of this.status.

Upvotes: 3

Related Questions