在键输入上停止并恢复无限循环

时间:2014-12-06 19:39:16

标签: java loops input infinite-loop

让我们说我们有一个无限循环,我们想让它睡一会儿,然后恢复它。我们没有设定时间,而是在按下按键时恢复它。

例如,在Java中我们可以:

while(true){
    doSomething();
}

现在,我们可以通过多种方式使这种中断。我们想在按键上打断它,所以我们将:

boolean running = true;
...
this.addKeyListener(this);
...
@override
public void keyPressed(KeyEvent e){
    running = false;
}

然后运行一个方法(让我们说run),其中包含:

while(running){
    doSomething();
}

但是我们遇到了一个问题:恢复。

因此我们采用keyPressed方法,并将其更改为:

running = !running;
if(running){
    run();
}

这里只有一个问题:在run方法完成之前,KeyListener不会做任何事情。我尝试过使用线程,我们会:

private class Runner implements Runnable {
    @Override
    public void run() {
        while (running) {
            doSomething();
        }
    }
}

keyPressed

if(running){
    runner.wait();
}else{
    runner.notify();
    runner.run();
}
running = !running;

但在我的实际代码中,doSomething方法是无法中断的代码(因为它处理输出到屏幕),因此永远不会调用thread.wait()(它会抛出异常)所有的时间,而不是实际上等待。)

那么,总结一下:如何使用Java中的键输入来停止和恢复循环?

2 个答案:

答案 0 :(得分:1)

waitnotify旨在从不同的线程调用。顾名思义,应该在暂停的线程中调用wait并等待通知条件已更改:

private final Object keyPressMonitor = new Object();

private boolean running = true;

private Runnable gameLoop = new Runnable() {
    @Override
    public void run() {
        try {
            synchronized (keyPressMonitor) {
                while (true) {
                    while (!running) {
                        keyPressMonitor.wait();
                    }
                    doSomething();
                }
            }
        } catch (InterruptedException e) {
            logger.log(Level.INFO,
                "Interrupted; cleaning up and exiting.", e);
        }
    }
};

另一个线程,可能是AWT事件调度线程,它是你的KeyListener(或ActionMap / InputMap绑定调用的Action)被调用的地方,通知循环线程,正确的键是按下或释放:

public void keyPressed(KeyEvent event) {
    if (event.getKeyCode() == theKeyICareAbout) {
        synchronized (keyPressMonitor) {
            running = true;
            keyPressMonitor.notifyAll();
        }
    }
}

public void keyReleased(KeyEvent event) {
    if (event.getKeyCode() == theKeyICareAbout) {
        synchronized (keyPressMonitor) {
            running = false;
            keyPressMonitor.notifyAll();
        }
    }
}

答案 1 :(得分:0)

您可以将Semaphore用于以下目的:

private static class Runner implements Runnable {
    private final AtomicInteger permits = new AtomicInteger(0);
    private final Semaphore semaphore = new Semaphore(1, true);
    private volatile boolean running;

    public void putToSleep() {
        semaphore.acquireUninterruptibly();
    }

    public void resume() {
        semaphore.release(permits.getAndSet(0));
    }

    @Override
    public void run() {
        while (running) {
            semaphore.acquireUninterruptibly(Integer.MAX_VALUE);
            semaphore.release(Integer.MAX_VALUE);
            doSomething();
        }
    }

    private void doSomething() {
        //...
    }
}