【问题标题】:"Thread already started" when resuming the activity恢复活动时“线程已启动”
【发布时间】:2010-06-30 10:05:32
【问题描述】:

这是我的情况: 我正在为 android 构建一个游戏,我的游戏活动由一个自定义的 surfaceView 组成,它有一个用于游戏逻辑和渲染的线程。该架构类似于 Google 网站上的 LunarLander 演示。

当activity启动时,它会创建surfaceView并调用这个方法:

    @Override
    public void surfaceCreated(SurfaceHolder holder)
    {   
        renderThread.start();
    }

当我按下home键退出游戏时,调用了onPause()方法,该方法调用了surfaceDestroyed()。在 surfaceDestroyed 中,我通过调用来停止游戏线程:

    @Override
    public void surfaceDestroyed(SurfaceHolder holder)
    {
        synchronized(holder)
        {
            renderThread.stop();
        }
    }       

应用程序进入后台正常。然后,当我通过按图标重新启动应用程序时,我会在日志中收到“线程已启动”消息以及屏幕上的“强制关闭”弹出窗口。当 Activity 在渲染线程上调用 start() 时进入“surfaceCreated”方法时会出现此消息。

现在我已经研究了几个小时,无法弄清楚这是为什么。我相信当我关闭应用程序时我的线程已停止,所以我不明白为什么它说它已经开始了。

【问题讨论】:

    标签: java android multithreading android-lifecycle


    【解决方案1】:

    这些方法并不像您认为的那样做。来自API doc

    启动线程是不合法的 不止一次。

    还有:

    public final void stop() - 已弃用。这种方法本质上是不安全的。

    如果你想暂停一个线程,你必须在线程内使用Object.wait()Objecft.notifyAll()

    【讨论】:

    • 您好,谢谢您的回答。我在 while 循环中用 join() 替换了 stop()。我相信它会在停止线程之前等待。但我仍然有同样的问题,我错过了什么吗?至于线程的开始。我知道线程不能多次启动,因此会出现错误消息。那么你认为我得到这个错误只是因为线程没有正确停止吗?谢谢
    • @NioX5199:不,join() 也不会停止线程,它会等待它自己完成。您收到错误是因为线程已经启动。线程不能被“停止”并重新启动。正如我所写:为了使线程暂停直到满足条件,您使用 Object.wait()。
    • 他可能也不应该那样做。重新创建线程可能是更好的方法。
    • 好的,谢谢。作为一种解决方法,我在重新启动线程之前检查线程的状态,如果它的状态是 TERMINATED 我只是重新创建它。我不确定这是否真的是我想要在这里做的。
    • 请分享检查线程状态的代码。有同样的问题。
    【解决方案2】:

    在我看来,如果您打算经常启动和停止 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) {
            }
        }
    }
    

    另外,依赖异常是不好的形式。当您自己的代码出现意外行为时,这应该作为最后的手段。

    【讨论】:

      【解决方案3】:

      一个糟糕的解决方案,但它有效..

       public void surfaceCreated(SurfaceHolder holder) {
              try{
              _thread.setRunning(true);
              _thread.start();
              }catch(Exception ex){
                  _thread = new TutorialThread(getHolder(), this);
                  _thread.start();
              }
      
          }
      

      欢迎指正。

      【讨论】:

      • 虽然这会起作用 (fsvo),但通常不是一个好主意,一味地捕捉问题然后尝试纠正。相反,要主动,并让异常恢复其含义。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2010-10-17
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多