我有以下代码:
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
变量。我可能需要某种线程间的通信。我是线程的新手,请告诉我如何做到这一点
答案 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可以将其他帖子中的一个标记为正确答案,我很乐意将其删除。