Is it legal to call the start method twice on the same Thread?

Solution 1:

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.

Solution 2:

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.

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

Solution 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