Stop thread and again start giving IllegalThreadStateException in blackberry
Asked Answered
W

2

13

I am getting IllegalThreadStateException exception when using following code: I have already started this thread once(by using thread.start()) and again trying to start it at another place, so used following code:

thread.interrupt();
thread.start();

But thread.start() is throwing IllegalThreadStateException.

What should I use to solve it?

Whomever answered 24/11, 2012 at 5:48 Comment(2)
just added java tag, since it is common to any java.Icbm
@VitKhudenko actually it already has java-me. But yeah it still needs java tagBlowing
H
21

Thread objects are only meant to be started once. If you need to stop/interrupt a Thread, and then want to start it again, you should create a new instance, and call start() on it:

thread.interrupt();  // if you need to make sure thread's run() method stops ASAP
thread = new MyThreadSubclass();
thread.start();

From the API docs

IllegalThreadStateException - if the thread was already started.

I know it's not 100% clear that you can't call start() again, even if you previously called interrupt(), but that's the way it works.

If you look at the API docs for standard Java, this issue is more clear.

Hydrosome answered 24/11, 2012 at 5:59 Comment(5)
Thanks Nate. But when I was trying to use 'thread.interrupt();' It is again showing exception as - IllegalThreadStateException.Whomever
@AnkitRox, the API docs don't show that interrupt() throws any exceptions. However, my guess would be that you're calling interrupt() even before the 1st time that you run this code. You really would only need to interrupt the thread if it's been started once. So, the 2nd, 3rd, etc. times you want to call start(), you might call interrupt() right beforehand. You could test thread.isAlive() before calling thread.interrupt(). If that doesn't work, you need to show some more code (e.g. how you create the Thread object).Hydrosome
I have a class as AsyncUploadQuestionsAndLeads which is extended by Thread. Initializing Thread object by using: AsyncUploadQuestionsAndLeads uploadThread = new AsyncUploadQuestionsAndLeads(event); And starting the thread from some other place: uploadThread.start(); After some time, I am using the code as: uploadThread.interrupt(); uploadThread.start(); This is my code procedure which I have followed. One more Question is - Does thread stops itself, when it completes it's run block?Whomever
Please read my answer. You can't call interrupt(), and then call start() right after that, on the same instance. If you are going to call start() a second time, you have to create a new instance with uploadThread = new AsyncUploadQuestionsAndLeads(event) again. And, yes, the thread essentially stops when the run() method completes. After run() completes, you cannot call start() again on the same instance. You must create a new one.Hydrosome
Thanks Nate. I was also trying your method. But the problem occurred at that time was, it was start a new thread for the new instance and previous thread was also working.Whomever
I
9

In addition to Nate's answer.

AnkitRox states in his comment:

Thanks Nate. I was also trying your method. But the problem occurred at that time was, it was start a new thread for the new instance and previous thread was also working.

So it looks like the problem is "the thread is still running even if I called interrupt on it". Consider this sample (it is ugly, but enough to show the main idea):

final Thread t = new Thread(new Runnable() {
    public void run() {
        while (true) {
            for (int i = 0; i < 100000000; i++); // simulate some action
            System.out.println("hi, interrupted = " 
                    + Thread.currentThread().isInterrupted());
        }
    }
});
t.start();
new Timer(true).schedule(
    new TimerTask() {
        public void run() {
            t.interrupt();
        }
    },
    1000 // 1 second delay
);

Note, the thread continues to run even after interrupt() has been called. The produced output is:

hi, interrupted = false
hi, interrupted = true
hi, interrupted = true
hi, interrupted = true
...
hi, interrupted = true

Actually the programm never stops unless closed forcefully. So what then the interrupt() does? It just sets the interrupted flag to true. After interrupt() has been called the Thread.currentThread().isInterrupted() starts to return false. And that's all.

Another case is if interrupt() is called while the thread is blocked in an invocation of one of the methods that throw InterruptedException, then that method will return throwing the InterruptedException. And if thread's code just "eats" that exception, then the thread will still continue running, consider a sample:

final Thread t = new Thread(new Runnable() {
    public void run() {
        while (true) {
            System.out.println("hi, interrupted = " 
                    + Thread.currentThread().isInterrupted());
            try {
                Thread.sleep(5000);
            } catch (InterruptedException e) {
                System.out.println("got InterruptedException");
            }
        }
    }
});
t.start();
new Timer(true).schedule(
    new TimerTask() {
        public void run() {
            t.interrupt();
        }
    },
    1000 // 1 second delay
);

Note, the thread continues to run even after interrupt() has been called. The produced output is:

hi, interrupted = false
got InterruptedException
hi, interrupted = false
hi, interrupted = false
...
hi, interrupted = false

Note, this time interrupted = false even after interrupt() has been called. This is because whenever InterruptedException is caught, the interrupted flag is reset to false.

In Java stopping a thread is cooperative mechanism. Meaning it can not be done without cooperation from the thread itself. Here is the fixed version of the above sample:

final Thread t = new Thread(new Runnable() {
    public void run() {
        while (!Thread.currentThread().isInterrupted()) {
            System.out.println("hi, interrupted = " 
                    + Thread.currentThread().isInterrupted());
            try {
                Thread.sleep(5000);
            } catch (InterruptedException e) {
                System.out.println("we've been interrupted");
                // restore the interrupted flag
                Thread.currentThread().interrupt();
            }
        }
    }
});
t.start();
new Timer(true).schedule(
    new TimerTask() {
        public void run() {
            t.interrupt();
        }
    },
    1000 // 1 second delay
);

So the correct approach should be to periodically check the interrupted flag. And if interrupted status is detected then just return ASAP. Another common option is not to use Thread.interrupt() at all, but some custom boolean instead.

Icbm answered 25/11, 2012 at 14:47 Comment(1)
great explanation. not ugly at all :)Hydrosome

© 2022 - 2024 — McMap. All rights reserved.