让我们说我们有一个无限循环,我们想让它睡一会儿,然后恢复它。我们没有设定时间,而是在按下按键时恢复它。
例如,在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中的键输入来停止和恢复循环?
答案 0 :(得分:1)
wait
和notify
旨在从不同的线程调用。顾名思义,应该在暂停的线程中调用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() {
//...
}
}