简体   繁体   English

在Java中后台运行线程

[英]Run thread in background in java

I'm writing a chess program in java. 我正在用Java编写国际象棋程序。 So far things are coming along fine but I do have a problem with updating my UI. 到目前为止,一切进展顺利,但我确实无法更新UI。

Here's a snippet of code from class ChessBoard which extends JPanel. 这是ChessBoard类的代码片段,它扩展了JPanel。 This is called when a user tries to make a move: 用户尝试移动时调用此方法:

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
}

The thread is calling "run" on my instance of ChessBoard. 线程在我的ChessBoard实例上调用“运行”。 The algorithm that finds the move can take several seconds to decide on a move. 找到移动的算法可能需要几秒钟来决定移动。

I would like for my UI to update to reflect the user's move and then run the algorithm. 我希望用户界面进行更新以反映用户的移动,然后运行算法。 That's why I run the algorithm on a separate thread. 这就是为什么我在单独的线程上运行算法的原因。 But my UI is not being updated until the computer also makes a move. 但是直到计算机也采取行动之前,我的UI才会更新。

So if the user clicks a space to send a piece there, the screen freezes and then all of a sudden the piece has moved but the computer has moved also and it is again the player's turn. 因此,如果用户单击一个空格将一块发送到该处,屏幕将冻结,然后突然该块已移动,但计算机也已移动,现在轮到玩家了。

Any help will be greatly appreciated. 任何帮助将不胜感激。

thread.run() is going to execute the code in the thread's run method on the current thread. thread.run()将在当前线程上执行线程的run方法中的代码。 You want thread.start() . 您需要thread.start()

Relevant JavaDoc 相关的JavaDoc

The repaint method doesn't actually repaint immediately. repaint方法实际上并不会立即重绘。 It basically tells the JPanel that it ought to repaint itself soon. 它基本上告诉JPanel它应该尽快重新粉刷自己。 Then you go ahead on the same thread and calculate the AI's move, which will freeze the window because Swing isn't multi-threaded. 然后,您在同一线程上继续操作并计算AI的移动,这将冻结窗口,因为Swing不是多线程的。

First, threads are not re-entrant (I'll explain that in a moment). 首先,线程不是可重入的(稍后我将对此进行解释)。

thread.run() is not causing the thread to execute in a separate thread, it's just call the run method of the thread (within the current Thread s context. thread.run()不会导致线程在单独的线程中执行,它只是调用线程的run方法(在当前Thread的上下文中)。

What you need to do is set up a condition loop within your Thread that you can trigger in order to execute the logic you need. 您需要做的是在您的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...
        }
    }
}

Now, Thread s are non-reentrant, this means that once the run method has complete, that instance of the Thread can not be restarted. 现在, Thread是不可重入的,这意味着一旦run方法完成,就无法重新启动该Thread实例。

Hence using thread.start() more then once will not work (can't remember if it throws an exception or not) (hence the reason I prefer Runnable ) 因此,多使用一次thread.start()将不起作用(不记得它是否引发异常)(因此,我更喜欢Runnable的原因)

So. 所以。 What you want to do, is start the Thread when your program loads and when you need to, call thread.doNextMove() to cause it calculate the what ever it is you need. 您想要做的是在程序加载时启动Thread ,并在需要时调用thread.doNextMove()使其计算所需的内容。

Now, also remember, Swing is not Thread safe. 现在,还请记住, Swing不是Thread安全的。 That is, you should NEVER update the UI from any Thread other than the Event Dispatching Thread (or EDT) 也就是说,除了事件调度线程 (或EDT)之外,您永远不要从任何Thread更新UI。

You might also want to have a read through Concurrency in Swing 您可能还想通读Swing中的并发性

Oh and Concurrency in Java ,Java中的并发

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM