92

The following code leads to java.lang.IllegalThreadStateException: Thread already started when I called start() method second time in program.

updateUI.join();    

if (!updateUI.isAlive()) 
    updateUI.start();

This happens the second time updateUI.start() is called. I've stepped through it multiple times and the thread is called and completly runs to completion before hitting updateUI.start().

Calling updateUI.run() avoids the error but causes the thread to run in the UI thread (the calling thread, as mentioned in other posts on SO), which is not what I want.

Can a Thread be started only once? If so than what do I do if I want to run the thread again? This particular thread is doing some calculation in the background, if I don't do it in the thread than it's done in the UI thread and the user has an unreasonably long wait.

Ravindra babu
  • 37,698
  • 11
  • 250
  • 211
Will
  • 19,789
  • 10
  • 43
  • 45

11 Answers11

118

From the Java API Specification for the Thread.start method:

It is never legal to start a thread more than once. In particular, a thread may not be restarted once it has completed execution.

Furthermore:

Throws:
IllegalThreadStateException - if the thread was already started.

So yes, a Thread can only be started once.

If so than what do I do if I want to run the thread again?

If a Thread needs to be run more than once, then one should make an new instance of the Thread and call start on it.

coobird
  • 159,216
  • 35
  • 211
  • 226
  • Thanks. I checked the documentation with the IDE and the Java tutorial for threads (and google too). I'll check the API spec in the future. That critical "..never legal to start more than once.." is not in the other readings. – Will Aug 01 '09 at 01:51
  • @coobird, if I assign the old thread object name to a new Thread(), after the old thread has finished, will the old thread be garbage collected (i.e. is it automatically recycled, or must this be done explicitly)? – snapfractalpop Apr 05 '12 at 05:17
  • It will be garbage collected, as long as the Thread is no longer running. – natewelch_ Feb 07 '13 at 20:50
  • 1
    This answer is a bit out-of-date. If a modern Java program needs to perform a _task_ more than once, then it should not create a new `Thread` each time. Instead, it should submit the task to a _thread pool_ (e.g., `java.util.concurrent.ThreadPoolExecutor`) – Solomon Slow Jun 23 '17 at 14:50
14

Exactly right. From the documentation:

It is never legal to start a thread more than once. In particular, a thread may not be restarted once it has completed execution.

In terms of what you can do for repeated computation, it seems as if you could use SwingUtilities invokeLater method. You are already experimenting with calling run() directly, meaning you're already thinking about using a Runnable rather than a raw Thread. Try using the invokeLater method on just the Runnable task and see if that fits your mental pattern a little better.

Here is the example from the documentation:

 Runnable doHelloWorld = new Runnable() {
     public void run() {
         // Put your UI update computations in here.
         // BTW - remember to restrict Swing calls to the AWT Event thread.
         System.out.println("Hello World on " + Thread.currentThread());
     }
 };

 SwingUtilities.invokeLater(doHelloWorld);
 System.out.println("This might well be displayed before the other message.");

If you replace that println call with your computation, it might just be exactly what you need.

EDIT: following up on the comment, I hadn't noticed the Android tag in the original post. The equivalent to invokeLater in the Android work is Handler.post(Runnable). From its javadoc:

/**
 * Causes the Runnable r to be added to the message queue.
 * The runnable will be run on the thread to which this handler is
 * attached.
 *
 * @param r The Runnable that will be executed.
 *
 * @return Returns true if the Runnable was successfully placed in to the
 *         message queue.  Returns false on failure, usually because the
 *         looper processing the message queue is exiting.
 */

So, in the Android world, you can use the same example as above, replacing the Swingutilities.invokeLater with the appropriate post to a Handler.

Bob Cross
  • 22,116
  • 12
  • 58
  • 95
  • The OP is asking about threading on Android, which does not include the SwingUtilities. – Austyn Mahoney Oct 04 '10 at 23:51
  • @Austyn, you're right. I added the remarks about Handler.post() to illustrate the parallel Android code. – Bob Cross Oct 05 '10 at 14:31
  • 1
    Another way if you are just trying to update your UI is to use `RunOnUIThread(Runnable)` or `View.post(Runnable)` instead of creating your own Handler. These will run the runnable on the main thread allowing you to update the UI. – Austyn Mahoney Oct 05 '10 at 22:06
4

No, we cannot start Thread again, doing so will throw runtimeException java.lang.IllegalThreadStateException. >

The reason is once run() method is executed by Thread, it goes into dead state.

Let’s take an example- Thinking of starting thread again and calling start() method on it (which internally is going to call run() method) for us is some what like asking dead man to wake up and run. As, after completing his life person goes to dead state.

public class MyClass implements Runnable{

    @Override
    public void run() {
           System.out.println("in run() method, method completed.");
    }

    public static void main(String[] args) {
                  MyClass obj=new MyClass();            
        Thread thread1=new Thread(obj,"Thread-1");
        thread1.start();
        thread1.start(); //will throw java.lang.IllegalThreadStateException at runtime
    }

}

/*OUTPUT in run() method, method completed. Exception in thread "main" java.lang.IllegalThreadStateException at java.lang.Thread.start(Unknown Source) */

check this

Sameer Kazi
  • 17,129
  • 2
  • 34
  • 46
3

The just-arrived answer covers why you shouldn't do what you're doing. Here are some options for solving your actual problem.

This particular thread is doing some calculation in the background, if I don't do it in the thread than it's done in the UI thread and the user has an unreasonably long wait.

Dump your own thread and use AsyncTask.

Or create a fresh thread when you need it.

Or set up your thread to operate off of a work queue (e.g., LinkedBlockingQueue) rather than restarting the thread.

CommonsWare
  • 986,068
  • 189
  • 2,389
  • 2,491
3

What you should do is create a Runnable and wrap it with a new Thread each time you want to run the Runnable. It would be really ugly to do but you can Wrap a thread with another thread to run the code for it again but only do this is you really have to.

Peter Lawrey
  • 525,659
  • 79
  • 751
  • 1,130
1

It is as you said, a thread cannot be started more than once.

Straight from the horse's mouth: Java API Spec

It is never legal to start a thread more than once. In particular, a thread may not be restarted once it has completed execution.

If you need to re-run whatever is going on in your thread, you will have to create a new thread and run that.

alanlcode
  • 4,208
  • 3
  • 29
  • 23
0

To re-use a thread is illegal action in Java API. However, you could wrap it into a runnable implement and re-run that instance again.

Aaron He
  • 51
  • 1
0

Yes we can't start already running thread. It will throw IllegalThreadStateException at runtime - if the thread was already started.

What if you really need to Start thread: Option 1 ) If a Thread needs to be run more than once, then one should make an new instance of the Thread and call start on it.

riteeka
  • 69
  • 1
  • 6
0

Can a Thread be started only once?

Yes. You can start it exactly once.

If so than what do I do if I want to run the thread again?This particular thread is doing some calculation in the background, if I don't do it in the thread than it's done in the UI thread and the user has an unreasonably long wait.

Don't run the Thread again. Instead create Runnable and post it on Handler of HandlerThread. You can submit multiple Runnable objects. If want to send data back to UI Thread, with-in your Runnable run() method, post a Message on Handler of UI Thread and process handleMessage

Refer to this post for example code:

Android: Toast in a thread

Ravindra babu
  • 37,698
  • 11
  • 250
  • 211
-1

I don't know if it is good practice but when I let run() be called inside the run() method it throws no error and actually does exactly what I wanted.

I know it is not starting a thread again, but maybe this comes in handy for you.

public void run() {

    LifeCycleComponent lifeCycleComponent = new LifeCycleComponent();

    try {
        NetworkState firstState = lifeCycleComponent.getCurrentNetworkState();
        Thread.sleep(5000);
        if (firstState != lifeCycleComponent.getCurrentNetworkState()) {
            System.out.println("{There was a NetworkState change!}");
            run();
        } else {
            run();
        }
    } catch (SocketException | InterruptedException e) {
        e.printStackTrace();
    }
}

public static void main(String[] args) {
    Thread checkingNetworkStates = new Thread(new LifeCycleComponent());
    checkingNetworkStates.start();
}

Hope this helps, even if it is just a little.

Cheers

Diorcula
  • 105
  • 2
  • 12
-1

It would be really ugly to do but you can Wrap a thread with another thread to run the code for it again but only do this is you really have to.

I have had to fix a resource leak that was caused by a programmer who created a Thread but instead of start()ing it, he called the run()-method directly. So avoid it, unless you really really know what side effects it causes.

Torben
  • 3,805
  • 26
  • 31
  • But the suggestion was not to call `run()` directly, just to embed a Runnable in a Thread and presumably invoke `start()`. – H2ONaCl Dec 19 '11 at 17:39
  • @H2ONaCl If you read the text I quoted, the suggestion was to wrap a Thread in a Thread. It may be that you didn't get to read the original suggestion before it was edited. – Torben Jul 03 '17 at 06:54