简体   繁体   中英

Thread.join() and Thread.interrupt() doesn't stop the thread

I'm having some issues with stopping my threads.
I've tried calling both Thread.join() and Thread.interrupt() , alone and together, but I can't get it working.
I have a while loop in each class, which runs as long as a boolean called running equals to true .
I then stop the program by calling a method called stop . The stop method only sets running to false, so that the while loop exits.

EDIT Code:

public class Game implements Runnable {

    // The Thread
    private Thread thread;

    // The program's running state
    private boolean running = false;

    // Create the Thread and the rest of the application
    public void create() {
        // Create the Thread
        thread = new Thread(this, "Game");
        // Start the Thread
        thread.start();
        // Set the program's running state to true
        running = true;
    }

    public void run() {
        while(running) {
            // Render, update etc...
        }

        // When the while loop has exited
        // (when running is false (when the stop method has been called))
        try {
            // Join the thread
            thread.join();
            // Interrupt the thread
            thread.interrupt();
        } catch(InterruptedException e) {
            // Print the exception message
            e.printStackTrace();
        }
        // Exit the program
        System.exit(0);
    }

    // Stop the game
    public void stop() {
        // Set the program's running state to false
        running = false;
    }

    // The main method
    public static void main(String[] args) {
        // Create a new instance of Game and start it
        new Game().create();
    }

The thread blocks itself
A thread ends, when the run method is finished, but you call the join() method inside the run() method and this method waits until the thread is finished. So the run() method never ends and the thread will never die.
You have done correct, to implement a while, which tests a boolean you can set in a method to end the thread.
To end the thread and waiting on its end, call the join() method after calling the stop() .
The System.exit(0) in the run method is not needed. If your thread ends and the join() method returns, the main method ends and so the program is finished.I know, your real program will be more complex, but you don't need System.exit() .

public void run() {
    while(running) {
        // Render, update etc...
    }
}

// The main method
public static void main(String[] args) {
    // Create a new instance of Game and start it
    Game game = new Game().create();
    game.stop();
}

EDIT 1:

// Stop the game
public void stop() {
    // Set the program's running state to false
    running = false;
    game.interrupt();//Cause blocking methods like Thread.sleep() to end with an Interrupted exception
    game.join();//Wait until the thread is completed
}

I believe you should rewrite your run() method:

public void run() {
    while(true) {
        // Render, update etc...

        // at the end, or after some steps, according to Java doc for Thread
        if (Thread.interrupted())  
           throw new InterruptedException();
    }
}

And your stop() method, simply interrupting the thread should do it:

public void stop() {
    thread.interrupt();  //use thread here, not game
}    

Add a join() method:

public void join() throws InterruptedException {
    thread.join(); 
}    

So in your main, you join your thread

public static void main(String[] args) {
    // Create a new instance of Game and start it
    Game game = new Game();
    game.create();
    try {
        game.join();
    } catch (InterruptedException e) {
        //The interrupt should occur from another thread

        //Somebody called stop()
        //do your clean up
        System.exit(0);
    }           
}   

This is the related JavaDoc .

What is not clear to me yet, is how exactly you invoke stop().

As far as I understand you need to stop all your threads when your game exits from main. You can setDaemon(true) to all your threads and they will be closed automatically.

Read about setDaemon in documentation http://docs.oracle.com/javase/7/docs/api/java/lang/Thread.html#setDaemon(boolean)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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