【问题标题】:Thread.join() and Thread.interrupt() doesn't stop the threadThread.join() 和 Thread.interrupt() 不会停止线程
【发布时间】:2015-02-12 16:56:29
【问题描述】:

我在停止线程时遇到了一些问题。
我试过单独和一起打电话给Thread.join()Thread.interrupt(),但我无法正常工作。
我在每个类中都有一个while 循环,只要一个名为running 的布尔值等于true,它就会运行。
然后我通过调用一个名为stop 的方法来停止程序。 stop 方法仅将 running 设置为 false,以便退出 while 循环。

编辑代码:

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

【问题讨论】:

  • 没有足够的代码。请注意,检查线程是否被中断的标准方法是检查Thread.currentThread().isInterrupted()。仔细阅读 javadoc。或者更好的是,不要直接使用线程并使用ExecutorService。并购买 JCIP。
  • 对不起,我没有提到我在创造一个游戏,所以不使用线程不是一个选项。另外,你需要多少代码?
  • 你真的认为 join() 和 interrupt() 会将你的 running 变量设置为 false 吗?这就是那些方法的 javadoc 所说的吗?
  • 这是它的基础。我把所有的渲染等都放在了循环里面。
  • @user1676075 AtomicBooleanvolatile 之外没有任何东西,如果你只需要setget

标签: java multithreading loops


【解决方案1】:

线程自己阻塞
当 run 方法完成时,线程结束,但是您在 run() 方法中调用 join() 方法,并且此方法一直等到线程完成。所以run() 方法永远不会结束,线程永远不会死。
你做对了,实现了一段时间,它测试了一个布尔值,你可以在方法中设置一个结束线程。
要结束线程并等待其结束,请在调用stop() 之后调用join() 方法。
不需要运行方法中的System.exit(0)。如果你的线程结束,join() 方法返回,main 方法结束,程序就结束了。我知道,你真正的程序会更复杂,但你不需要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();
}

编辑 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
}

【讨论】:

  • 那么我做错了什么是我在run()方法中调用了thread.join()
  • 是的,这会导致线程等到结束,但这永远不会发生。如果使用 interrupt() 方法,join() 方法将结束,线程也将结束。但是您必须从 run 方法之外调用中断。但是没有必要做任何事。
  • 所以我应该在mainstop方法中调用thread.interrupt()然后thread.join(),并将running设置为false,以使线程和游戏停止?
  • 是的,看看EDIT1试试吧。
【解决方案2】:

我认为你应该重写你的 run() 方法:

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

而您的 stop() 方法,只需中断线程即可:

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

添加一个 join() 方法:

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

所以在你的主线中,你加入你的线程

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);
    }           
}   

这是相关的JavaDoc

我还不清楚你是如何调用 stop() 的。

【讨论】:

  • 对不起,我忘记了。当JFrame 被关闭时调用停止。
  • 我会在我的电脑上试试。
【解决方案3】:

据我了解,当您的游戏从 main 退出时,您需要停止所有线程。 您可以将所有线程 setDaemon(true),它们将自动关闭。

在文档中了解 setDaemon http://docs.oracle.com/javase/7/docs/api/java/lang/Thread.html#setDaemon(boolean)

【讨论】:

  • 来自文档:当唯一运行的线程都是守护线程时,Java 虚拟机退出。因此,这意味着如果您的应用程序中只有守护线程,应用程序将被关闭。所有线程也将关闭。
猜你喜欢
  • 2014-05-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-03-11
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多