java 恢复活动时“线程已启动”
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/3148186/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
"Thread already started" when resuming the activity
提问by NioX5199
Here is my situation: I am building a game for android and my game's activity is composed of a custom surfaceView which has a thread for the game logic and rendering. The architecture is similar to the LunarLander demo from Google's website.
这是我的情况:我正在为 android 构建一个游戏,我的游戏活动由一个自定义的 SurfaceView 组成,它有一个用于游戏逻辑和渲染的线程。该架构类似于 Google 网站上的 LunarLander 演示。
When the activity starts it creates the surfaceView and calls this method:
当活动开始时,它会创建surfaceView并调用这个方法:
@Override
public void surfaceCreated(SurfaceHolder holder)
{
renderThread.start();
}
When I press the home button to exit the game, the onPause() method is called, which calls surfaceDestroyed(). In surfaceDestroyed I stop the game Thread by calling:
当我按下home键退出游戏时,onPause()方法被调用,该方法调用surfaceDestroyed()。在surfaceDestroyed中,我通过调用来停止游戏线程:
@Override
public void surfaceDestroyed(SurfaceHolder holder)
{
synchronized(holder)
{
renderThread.stop();
}
}
The app goes to background fine. Then, when I relaunch the app by pressing the icon, I get a "Thread already started" message in the log along with a "force close" popup on the screen. This message happens when the activity enters the "surfaceCreated" method when it calls start() on the render thread.
该应用程序进入后台正常。然后,当我通过按下图标重新启动应用程序时,我会在日志中收到一条“线程已启动”消息,并在屏幕上显示“强制关闭”弹出窗口。当活动在渲染线程上调用 start() 时进入“surfaceCreated”方法时,会发生此消息。
Now I've looked into it for hours and can't figure out why this is. I believe my thread is stopped when I close the app so I don't understand why it says it has already started.
现在我已经研究了几个小时,但不知道为什么会这样。我相信当我关闭应用程序时我的线程已停止,所以我不明白为什么它说它已经开始。
采纳答案by Michael Borgwardt
Those methods don't do what you think they do. From the API doc:
这些方法不会做您认为它们会做的事情。来自API 文档:
It is never legal to start a thread more than once.
多次启动一个线程是不合法的。
And:
和:
public final void stop()- Deprecated. This method is inherently unsafe.
public final void stop()- 已弃用。这种方法本质上是不安全的。
If you want to pause a thread, you have to use Object.wait()and Objecft.notifyAll()from within the thread.
如果要暂停线程,则必须在线程内使用Object.wait()和Objecft.notifyAll()。
回答by Torben
In my opinion you should not pack your code into a subclass of Thread if you intend to be starting and stopping the Thread often (the examples do it because it makes the code shorter). Use a Runnable instead. That way you can stop and discard the old Thread when you want and create a new Thread object to execute the Runnable when you need to start it again.
在我看来,如果您打算经常启动和停止 Thread,则不应将代码打包到 Thread 的子类中(示例这样做是因为它使代码更短)。请改用 Runnable。这样,您可以在需要时停止并丢弃旧的 Thread,并在需要再次启动它时创建一个新的 Thread 对象来执行 Runnable。
private TutorialRunnable tutorialRunnable;
...
// Synchronization and error checking omitted for brevity.
public void surfaceCreated(SurfaceHolder holder) {
thread = new Thread(tutorialRunnable);
thread.start();
}
public void surfaceDestroyed(SurfaceHolder holder) {
tutorialRunnable.setRunning(false);
while (thread != null) {
try {
thread.join();
thread = null;
} catch (InterruptedException e) {
}
}
}
Also, relying on exceptions is bad form. That should be used as a last resort when your own code behaves unexpectedly.
此外,依赖异常是不好的形式。当您自己的代码出现意外行为时,这应该用作最后的手段。
回答by AZ_
A bad solution but it works..
一个糟糕的解决方案,但它有效..
public void surfaceCreated(SurfaceHolder holder) {
try{
_thread.setRunning(true);
_thread.start();
}catch(Exception ex){
_thread = new TutorialThread(getHolder(), this);
_thread.start();
}
}
corrections are warmly welcomed.
热烈欢迎更正。

