我正在创建一个运行一些线程的图形界面。这些线程中的每一个都启动一个Java进程来管理VNC连接。我想要的只是通过将其存储在管理线程的一些变量中来跟踪进程的生命周期。最后,GUI与线程通信以了解进程状态。
下面是我的代码片段:
public class VNCViewer extends Thread{
private static final String cmd = "some command";
private Process vnc;
private boolean active = false ;
public void run(){
try {
launchVNC();
} catch (IOException ex) {
Logger.getLogger(VNCViewer.class.getName()).log(Level.SEVERE, null, ex);
} catch (InterruptedException ex) {
Logger.getLogger(VNCViewer.class.getName()).log(Level.SEVERE, null, ex);
}
}
private void launchVNC() throws IOException, InterruptedException{
if (condition){
vnc = Runtime.getRuntime().exec(cmd);
active = true;
while(vnc.isAlive()){} //while the process is alive, the thread awaits
active = false;
}
}
public boolean isActive(){
return active;
}
}
在运行时发生的事情是线程跳过"while"循环(我已经尝试通过在循环中插入system.out.println,并且仅在线程终止时才打印),结果变量"active"始终处于"false"。
由于active
不是volatile
,不在同步块中更新/访问,也不是Atomic*
类之一,因此Java VM假设没有人读取active=true
和active=false
之间的字段是完全合法的。
因此,它可以决定忽略active=true
(或者更准确地说,不将新值发布给其他线程)。
你需要正确地同步你的代码,在这种情况下声明volatile
字段就足够了:
private volatile boolean active = false;
这确保了对该字段的所有更新将立即发布,并且任何读取该字段的其他线程都将看到更新的字段。
我仍然不相信旋转外部进程关闭,但这是另一回事。