2012-08-30 139 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