【问题标题】:Java - Thread Doesn't StopJava - 线程不会停止
【发布时间】:2016-06-05 20:48:08
【问题描述】:

我有以下嵌套在另一个类中的类(也扩展了线程)

public class Miner extends Thread {
    private volatile boolean running = true;

    public void setRunning(boolean running) {
        this.running = running;
    }
    public boolean getRunning() {
        return running;
    }

    private void MainLoop() {
        if(!running) {
            robot.keyRelease(KeyEvent.VK_D);
            return;
        }
        robot.keyPress(KeyEvent.VK_D);
        robot.keyRelease(KeyEvent.VK_D);
        try {
            Thread.sleep(100 + (int)(Math.random()*randInt));
        } catch(Exception e) {}

        MainLoop();
    }

    @Override
    public void run() {
        MainLoop();
    }
}

然后在我嵌套 Miner 的类中

private void MainLoop() throws AWTException {
    Miner miner = new Miner();
    miner.start();
    ... does other stuff ...
    while(miner.getRunning())
        miner.setRunning(false);
    ... do more stuff ...
    MainLoop();
}

但是,在我尝试将运行设置为 false 并停止矿工线程并做“做更多事情”之后,我一直在做“做更多事情”,但它仍然按下 D 键。

包含 Miner 的类的完整 MainLoop() 方法。

private void MainLoop() throws AWTException {
        if(stop)
            return;
        Miner miner = new Miner();
        miner.start();
        while(true) {
            BufferedImage screenCap = robot.createScreenCapture(new Rectangle(x, y, 1, 1));
            int c = screenCap.getRGB(0,0);
            int  red = (c & 0x00ff0000) >> 16;
            int  green = (c & 0x0000ff00) >> 8;
            int  blue = c & 0x000000ff;
            Color color = new Color(red,green,blue);
            if(color.equals(DRILL_COLORS[0]) || color.equals(DRILL_COLORS[1]))
                break;
            try {
                Thread.sleep(500);
            } catch(Exception e) {}
            if(stop)
                return;
        }
        while(miner.getRunning())
            miner.setRunning(false);
        count++;
        if(count >= 3) {
            up = !up;
            count = 0;
        }

        switch(moveDir) {
            case 0:
                if(up)
                    holdKey(KeyEvent.VK_UP, 100 + (int)(Math.random()*randInt));
                else
                    holdKey(KeyEvent.VK_DOWN, 100 + (int)(Math.random()*randInt));
                break;
            case 1:
                if(up)
                    holdKey(KeyEvent.VK_RIGHT, 100 + (int)(Math.random()*randInt));
                else
                    holdKey(KeyEvent.VK_LEFT, 100 + (int)(Math.random()*randInt));
                break;
        }

        switch(wallLoc) {
            case 0:
                holdKey(KeyEvent.VK_UP, 50);
                break;
            case 1:
                holdKey(KeyEvent.VK_DOWN, 50);
                break;
            case 2:
                holdKey(KeyEvent.VK_RIGHT, 50);
                break;
            case 3:
                holdKey(KeyEvent.VK_LEFT, 50);
                break;
        }

        MainLoop();
    }

目标基本上是让 Miner 线程按下 D 键,直到它在我的屏幕上的某个点上检测到某种颜色。然后它应该在稍微移动我的角色时停止矿工线程,然后重新调用该方法并重新开始。但是矿工线程一直在运行。

【问题讨论】:

  • 在您的代码中,您有条件检查机器人是否正在运行,if(!running) {...}。在它的正下方,您还可以按下“D”键然后释放它。如果机器人running=truerunning=false,按键仍将执行。尝试注释掉robot.keyPress(KeyEvent.VK_D); 看看会发生什么。
  • if(!running) 块中,我释放键以确保它没有被按下,然后我调用 return 以便它不再循环方法。
  • 你是对的,抱歉没有注意到。
  • 介意把剩下的代码放在那里吗? “做更多的事情”位。我找不到那个片段的问题。可能是其他原因导致将running 设置回true
  • 我添加了其余的方法

标签: java multithreading key awtrobot


【解决方案1】:

这里没有stop conidion:

private void MainLoop() throws AWTException {
    Miner miner = new Miner();
    miner.start();
    ... does other stuff ...
    while(miner.getRunning())
        miner.setRunning(false);
    ... do more stuff ...
    MainLoop();
}

最后的方法调用自己=>MainLoop();,这是一个递归无限循环。
在这个方法中,一个新的Miner对象被创建,一个新的线程被启动,D被再次按下,然后线程被停止,然后...do more stuff..,然后整个循环又开始了。

【讨论】:

  • if(!running) 块中,虽然我放了一个return 声明,我认为这会停止挖矿。
  • if(runingMinesr 类中 - 这种情况会停止线程,但不会停止 private void MainLoop() 方法。
  • 我打算让循环基本上永远持续下去,但问题是miner 即使在“做更多事情”应该发生的时候仍然按 D。我在此之前停止线程的尝试不起作用。
  • 在 Miner#MainLoop 和 private#MainLoop 方法中插入一些日志(调试)命令,甚至简单的 System.out.println(...) 调用,您将在日志中看到代码的行为方式。
  • 我试过了,但问题是当做更多的事情时,矿工线程并没有停止,即使我在那之前就停止了它。