[英]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.