"Thread already started" when resuming the activity

13,052

Solution 1

Those methods don't do what you think they do. From the API doc:

It is never legal to start a thread more than once.

And:

public final void stop() - Deprecated. This method is inherently unsafe.

If you want to pause a thread, you have to use Object.wait() and Objecft.notifyAll() from within the thread.

Solution 2

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.

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.

Share:
13,052
NioX5199
Author by

NioX5199

Updated on July 24, 2022

Comments

  • NioX5199
    NioX5199 almost 2 years

    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.

    When the activity starts it creates the surfaceView and calls this method:

        @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:

        @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.

    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.

  • NioX5199
    NioX5199 almost 14 years
    Hi, thank you for the answer. I replaced stop() by a join() in a while loop. I believe it waits before stopping the thread. But I still have the same problem, am I missing something ? As for the start of thread. I understand that the thread cannot be started more than once hence the error message. So do you think that I get this error just because the thread is not properly stopped ? Thanks
  • Michael Borgwardt
    Michael Borgwardt almost 14 years
    @NioX5199: no, join() does not stop the thread either, it waits for it to finish on its own. You get the error because the Thread is already started. Threads cannot be "stopped" and restarted. As I wrote: for making a thread pause until a condition is fulfilled, you use Object.wait().
  • alexanderblom
    alexanderblom almost 14 years
    He should probably not do it that way either. Recreating the thread is probably a better approach.
  • NioX5199
    NioX5199 almost 14 years
    Ok thanks. As a workaround I check the status of the thread before restarting it and if its status is TERMINATED I just recreate it. I'm not sure if it's really what I want to do here though.
  • AZ_
    AZ_ over 13 years
    kindly share the code for checking thread status. Having same problem.
  • Michael Borgwardt
    Michael Borgwardt over 13 years
    @Aizaz: Thread.getState() - it's really not hard to take a look at the API docs yourself, you know.
  • Admin
    Admin over 11 years
    While this will work (fsvo), it's generally not a good idea to catch issues will-nilly and then to try and correct. Instead, be proactive and give Exceptions back their meaning.