[英]java.awt.Robot thread can't be stopped/destroyed?
我使用java.awt.Robot制作了桌面远程控制应用程序,并且工作正常。 应用程序集成在另一个应用程序系统中,所以我希望能够从外部系统启动/停止远程控制,我发现了奇怪的问题 - 我无法阻止机器人。
我尝试了几件事:在线程内运行它(所以我可以停止线程),使机器人对象为null而不是调用System.gc(),但问题不在于引用它的机器人线程仍在运行(在所有其他线程被销毁之后) )。 在调试中,我可以看到正在运行的线程:守护程序线程[AWT-Windows](正在运行)。
这是代码,将重现我的问题:
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)工具包).createRobot(this,screen);
通常你会在接收远程事件的线程的while(true)循环中放置一个标志,这样你就会有类似while(isAlive)...读取远程事件......如果远程事件断开连接你就会离开循环和机器人不再获得命令。
机器人只是活着,因为你的程序一直在调用它...你的停止循环
还包括在RobotThread中
import java.awt.AWTException;
import java.awt.Robot;
import java.util.LinkedList;
public class RobotDestroy {
public static void main(String[] args) {
//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("Init " + threadArray[i].getName()); }
RobotThread rt = new RobotThread();
rt.start();
// Listen to the upcomming commands...and push them to the RobotThread
rt.shutdown();
}
private static class RobotThread extends Thread {
public Robot robot;
public RobotThread(){
try {
this.robot = new Robot();
} catch (AWTException e) {
e.printStackTrace();
}
}
public void run(){
Command currentCommand = getNextCommand();
while(currentCommand.getType() != CommandType.KILL){
// Process the command no sleep...
// ...
// ...
currentCommand = getNextCommand();
}
System.out.println("DIED ");
}
private LinkedList<Command> commands = new LinkedList<Command>();
enum CommandType {
KILL,
DO_SOMETHING
}
private synchronized Command getNextCommand() {
while(commands.isEmpty()) {
try {
System.out.println("WAITING");
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
return commands.removeFirst();
}
public synchronized void pushCommand(Command comm) {
commands.addLast(comm);
notify();
}
public synchronized void shutdown(){
commands.clear();
pushCommand(new Command(CommandType.KILL));
System.out.println("shutdown");
//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("End " + threadArray[i].getName()); }
}
class Command {
private CommandType cmdType;
public Command(CommandType type) {
this.cmdType = type;
}
public CommandType getType() { return cmdType; }
}
}
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.