【发布时间】:2012-11-11 06:15:31
【问题描述】:
我使用 java.awt.Robot 制作了桌面远程控制应用程序,并且工作正常。 应用程序集成在另一个应用程序系统中,所以我希望能够从外部系统启动/停止远程控制,但我发现了一个奇怪的问题 - 我无法停止机器人。
我尝试了几件事:在线程内运行它(所以我可以停止线程),使机器人对象为空,而不是调用 System.gc() 但问题不在于引用它仍在运行的机器人线程(毕竟其他被摧毁)。 在调试中我可以看到正在运行的线程:Daemon Thread [AWT-Windows] (Running)。
这里是重现我的问题的代码:
public class RobotDestroy {
public static void main(String[] args) {
try {
Robot r = new Robot();
} catch (AWTException e) {
e.printStackTrace();
}
}
}
有没有人经历过类似的事情? 有什么解决办法吗?
谢谢
编辑:
这是在可以停止的线程中运行 Robot 但 Robot 实例仍在运行的示例:
public class RobotDestroy {
public static void main(String[] args) {
RobotThread rt = new RobotThread();
rt.start();
try {
//do some work before thread shut down
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
rt.shutdown();
}
private static class RobotThread extends Thread {
public Robot robot;
volatile boolean alive;
public RobotThread(){
try {
this.robot = new Robot();
this.alive = true;
} catch (AWTException e) {
e.printStackTrace();
}
}
public void run(){
while(alive){
System.out.println("alive");
try{
robot.delay(5000);
sleep(1000);
}catch(Exception e){
e.printStackTrace();
}
}
}
public void shutdown(){
this.alive = false;
robot = null;
System.out.println("shutdown");
}
}
}
编辑 2
我尝试了医生杀手的建议,虽然这是一个很好的建议,但机器人线程仍在运行。最好的证明方法是在创建机器人实例之前和之后打印出线程:
Set<Thread> threadSet = Thread.getAllStackTraces().keySet();
Thread[] threadArray = threadSet.toArray(new Thread[threadSet.size()]);
for (int i = 0; i < threadArray.length; i++) {
System.out.println(threadArray[i].getName());
}
更新: 经过大量调试后,我意识到问题不在于 java.awt.Robot 类 - 是 java.awt.Toolkit 启动了 AWT-Window 线程,该线程在应用程序结束后仍然运行。 Robot 对象具有 RobotPeer (java.awt.peer.RobotPeer),它由以下方法返回: ((ComponentFactory)toolkit).createRobot(this, screen);
【问题讨论】:
-
不可阻挡的机器人?这不好。
-
我手头没有直接证据,但我建议 tat Robot 实际上正在启动另一个非守护线程(如果我没记错的话,它正在启动 AWT EventQueue)。虽然您可以阻止机器人实例,但我知道的唯一方法是停止 EventQueue 一个 va System.exit
-
您是否尝试过使用调试器在剩余线程中停止执行以查看它实际在做什么?这可能会提示它为什么没有关闭。
-
在您上次更新后,您似乎确定了问题的根源……但是您是如何解决的? IE。您最终是如何停止 AWT-Window 线程的?
标签: java thread-safety awtrobot