2012-08-30 188 views
0

我正在用java寫一個國際象棋程序。到目前爲止,事情進展良好,但我更新我的用戶界面時遇到問題。在java中的後臺運行線程

這裏的代碼延伸JPanel類器ChessBoard片段。

if (isLegalMove(aMove)) { // If the move's legal 
    makeMove(aMove); // Make that move 
    select = null; // Reset some info 
    drag = null; 
    toggleTurn(); // Change turns 
    generateMoves(0); // Get legal moves for CPU 
    repaint(); // Redraw board 
    thread.run(); // Run chess algorithm 
} 

線程呼籲我的棋盤實例「運行」:這是當用戶試圖使一招叫。發現移動的算法可能需要幾秒鐘才能決定移動。

我想爲我的UI更新以反映用戶的舉動,然後運行該算法。這就是爲什麼我在一個單獨的線程上運行算法。但是我的用戶界面並沒有被更新,直到電腦也開始移動。

因此,如果用戶點擊一個空間,以發送一條那裏,屏幕凍結,然後突然一塊已經被移動,但計算機移動也並再次是玩家的回合。

任何幫助將不勝感激。

+0

讀你肯定然後將任何Thread更新UI需要很長時間才能運行的代碼在線程中?或者它在'generateMoves(0)'中?只需幾秒鐘就可以找到一個調試器。 – Strelok

回答

4

thread.run()會在線程的run方法執行當前線程的代碼。你需要thread.start()

Relevant JavaDoc

重繪方法實際上並沒有立即重新繪製。它基本上告訴JPanel它應該很快重新繪製。然後你繼續使用同一個線程並計算AI的移動,這將會凍結窗口,因爲Swing不是多線程的。

+0

我想你可能想重新考慮這個答案(來自OP的片段)。從[Java文檔](http://docs.oracle.com/javase/7/docs/api/java/lang/Thread.html#start%28%29)「*更多地啓動線程永遠不合法特別是,一旦線程完成執行後,線程可能不會重新啓動*「 – MadProgrammer

+0

@MadProgrammer儘管您說的是有效的,但是1)OP的主要問題」停止「行爲恰恰是由run( )方法,以及2)從代碼片段中,我們沒有線索OP是否正在重用線程實例。 OP有可能在if-block之外實例化線程 –

+0

@MadProgrammer正如Adrian所說,這裏唯一保證的問題是基於他的代碼,這是他調用了錯誤的方法。 JavaDoc的一部分將他與他聯繫起來,明確指出你不能多次啓動線程,所以如果他閱讀答案,他也會認爲這一部分也是。 –

1

首先,線程不重入(我將解釋在某一時刻)。

thread.run()不會導致線程在一個單獨的線程來執行,它只是調用線程的run方法(目前Thread的上下文中。

你需要做的是建立內部的條件環路什麼您Thread,你可以爲了執行你所需要的邏輯觸發。

public class ChessThread extends Thread { // I prefer Runnable, that's me 
    protected static final Object NEXT_MOVE_LOCK = Object(); 

    public ChessThread() { 
     setDaemon(true); // This will allow the JVM to exit without the need to terminate the thread... 
    } 

    public void doNextMove() { 
     // Notify the "wait" that we want to continue calculating the next move 
     synchronized (NEXT_MOVE_LOCK) { 
      NEXT_MOVE_LOCK.notify(); 
     } 
    }  

    public void run() { 
     while (true) { 
      // Wait for the "next move" request 
      synchronized (NEXT_MOVE_LOCK) { 
       try { 
        NEXT_MOVE_LOCK.wait(); 
       } catch (InterruptedException exp) { 
       } 
      } 
      // Calculate the next move... 
     } 
    } 
} 

現在,Thread s爲不可重入,這意味着一旦run方法有完整的Thread的該實例無法重新啓動。

因此,使用thread.start(),曾多次將無法正常工作(不記得,如果它拋出一個異常或不)(因此我更喜歡Runnable的原因)

所以。你想要做的是,當你的程序加載時,啓動Thread,當你需要時,請致電thread.doNextMove(),讓它計算出你需要的東西。

現在還記得,SwingThread安全。也就是說,你永遠不應該從不是Event Dispatching Thread(或EDT)其他

您也可能想通過Concurrency in Swing

哦,Concurrency in Java