繁体   English   中英

优雅地中断Java线程

[英]Interrupting a java thread gracefully

我写了一个Java ME益智游戏。 我是这样编写代码的:有一个线程在应用启动时启动,一旦游戏开始,就有另一个线程在无限循环中运行-主游戏循环。 第二个线程如下所示:

public void run() {
    init();
    while (shouldIRun) {            
        updateGameState();
        checkUserInput();
        updateGameScreen(getGraphics());
        this.flushGraphics();         
    }
}

可爱。 当我只是将布尔值shouldIRun设置为false时,该线程会一直运行,直到我想杀死它为止,然后它正常退出。

但是后来我意识到我想要更多。 该游戏是一款益智游戏,玩家可能会做出错误的举动然后陷入困境。 发生这种情况时,他们可以启动表单并选择“重新启动级别”选项。 然后设置一个标志restartLevel ,并且当无限循环到达updateGameState()方法时,该级别将重新启动。 但这对我来说就像是一场赌博-我不想开始更改并发问题时在主循环中使用的对象的变量,尽管我可能很偏执。 实际上,我意识到我想做的很清楚:我只是想暂停无限循环线程,将变量更改为我想要的,然后重新启动。

我已通过以下方式完成此操作:

public void run() {
    init();
    while (shouldIRun) {            

        if (shouldIWait) {
            iAmWaiting=true;
            while (shouldIWait) { };
            iAmWaiting=false;
        }

        updateGameState();
        checkUserInput();
        updateGameScreen(getGraphics());
        this.flushGraphics();
    }
}

我在想以下。 如果现在我想从“基本”线程中“暂停”第二个线程,只需将shouldIWait变量设置为true,然后循环直到我注意到iAmWaiting变量也为true。 我现在确定第二个线程已经暂停,并且我确切地知道了第二个线程已暂停的位置,“暂停”实际上是指“暂时卡在无限循环中”。 现在,我可以随意处理一些基本变量,重新启动级别,并大致进行分类,然后最后将shouldIWait设置为false,然后再次进行操作。

我的问题是:对我来说,这很好,但是有点k头。 是否有某种完全标准的方式来做可能是常见的事情- 在给定的位置暂停线程然后在我准备好后重新启动它,这比我正在做的要好? 我特别怀疑“将Java放入无限循环”可能不是一件聪明的事情。

通常,这就是使用Object.wait()Object.notify()的目的。

有两种方法可以根据您的情况实施它,但这是一个简单的示例:

Object monitor = new Object();
volatile boolean done = false, wait = false;

/* Running on one thread: */
public void run() {
    synchronized(monitor) {
        while(!done) {
            while(wait) {
                monitor.wait();
            }
            gameLogicAndStuff();
        }
    }
}

/* Running on another thread: */
public void showResetForm() {
    wait = true;
    synchronized(monitor) {
        actuallyShowResetForm();
        wait = false;
        monitor.notifyAll();
    }
}

也许杀死线程并以新级别开始新线程会更简单。

如果有一些信息需要从一个级别转移到另一个级别,则可以重构代码,以便首先收集一些常规信息,然后为每个级别启动一个线程。 (通过启动线程,我的意思是使用线程池。)

我不认为您当前正在忙着等待正在做什么,这不是邪恶的。 正如本·弗林(Ben Flynn)在评论中提到的那样,您可以通过遍历Thread.sleep(50)使其半忙。

暂无
暂无

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

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