2014-12-06 76 views
3

假設我們有一個無限循環,我們想讓它睡一會兒,然後重新開始。我們沒有設定的時間,而是在按下某個鍵時恢復它。停止並恢復鍵輸入的無限循環

例如,在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中的鍵輸入來停止和恢復循環的東西?

+1

你能告訴我們你試圖用線程? – Charlie 2014-12-06 19:42:36

+0

@Charlie我更新了帖子以包含該信息 – Wysaard 2014-12-06 20:06:41

+0

您應該在keyPressed中嘗試'runner.start()',這會形成一個平行線程,讓您的原始線程繼續 – Charlie 2014-12-06 20:08:39

回答

1

waitnotify旨在從不同的線程調用。

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(或:顧名思義,wait應當在暫停並等待被通知的情況已經改變了線程調用由關係的ActionMap/InputMap中綁定)調用的動作被調用時,會通知的循環線程正確鍵被按下或釋放:

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(); 
     } 
    } 
} 
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() { 
     //... 
    } 
}