I would like to stop this thread:
Runnable run = () -> { while(true)[...]; };
run.run();
But there is no run.stop() method.
Please suggest either an other as short as possible method to start and stop a thread or a method to stop this running... thing.
Runnable.run() does not create a thread. You're invoking the run() method in your current thread. To create a thread you need to do just that: create and start a thread:
Thread t = new Thread(run);
t.start();
Then later on you can invoke
t.interrupt();
Please read the javadocs on Thread.interrupt() on how to structure your run() method to be interruptable.
The simplest thing you normally do is to add a volatile boolean field to the runnable that is set by a different thread.
In your case you might perhaps use an AtomicBoolean instead of a volatile field and capture that in the closure. Once the closure is created, you can use this AtomicBoolean to stop.
In order to stop a thread ,first create a thread like this
Thread thread = new Thread(run);
and in order to start the thread
call
thread.start();
The start method will call run method but if you call run() method directly then no new thread will be created and the code will be executed in the existing thread. In order to stop the method you can use interrupt
Related
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.
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.
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.
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
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.
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.
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.
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.
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.
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
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.
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
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.
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.
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.
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
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.
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.
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.
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.
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.
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
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.
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
Will a thread simply terminate after it has completed its execution?
This is how I initialize my thread:
new Thread(new Runnable() {
public void run() {
}
}).start();
Basically what I am trying to do simply execute a single task on a new thread and then terminate the thread. However, after some time I will start another one and so forth. I don't want to have a bunch of threads started and I am wondering if the thread will terminate itself after complete ting it's execution?
Thanks.
Yes. When run returns, the thread will stop.
To execute a single task in a thread on Android, you might want to consider using AsyncTask instead. AsyncTask is designed exactly for this purpose. It gives you a simple way to pass data to the other thread, and pass progress updates and a final result back to the main thread. Each AsyncTask is like a Thread, but with those extra features.
Will a thread simply terminate after it has completed its execution?
Yes, It will terminate and exit itself after completing the run() method
Why do we need to run the thread through start method and not directly through the run method ?
The run method just executes the thread's task in the current thread. Historically, you would subclass Thread and override run - although today the preferred mechanism is to pass the Thread constructor a Runnable. So run itself doesn't do any threading - it's start which creates a new "actual" thread (as opposed to just a Thread object) and makes it execute run() when it's started.
Because the run method contains the code that the new thread should execute.
If you were to call the run method, then you'd just execute it on the current thread.
Calling start starts the new thread and then executes the run method on the new thread.
The start() method tells the JVM that it needs to create a system specific thread. After creating the system resource, it passes the Runnable object to it to execute its run() method. Calling the run() method directly has the "Thread" execute in the same thread as the calling object, not in a separate thread of execution, as intended.
In other words, calling run() is just like a normal method call. Whereas, calling start() tells the thread to create the necessary system resources and then execute the run() method asynchronously.
EDIT:
For example,
Pseudo code1:
thread one = new thread();
thread two = new thread();
one.run();
two.run();
This makes the threads run sequentially,ie, two.run(); will run only after one.run(); finishes.
Pseudo code2:
thread one = new thread();
thread two = new thread();
one.start();
two.start();
In this case both threads start and run simultaneously.
The start() method calls the run() method asynchronously (doesnt waits for any result, just fires up an action), but when WE call run(), it runs synchronously, ie,it waits until run() finishes and only then it proceeds to the next line of code.
in java Thread is always created in Stack Memory.When you create a new Thread it takes new memory in Stack.When you call start() method it initialize in new Stack Memory and when you call run() method it initialize in same Stack Memory
That is why we always call a Thread with start() method
in the main method if I write this:
Thread aThread = new Thread();
aThread.run();
what will happen???
It will run in current thread. You will not start new thread this way.
But that doesn't really matter in your example since you gave new Thread no code to run anyway.
The thread that runs the main() code is the current thread. Creating a Thread object and calling one of its methods (other than start()) is like calling a method of class Integer or String - it doesn't create a new actual thread.
In your code example, execution of the main method will continue only when the run() method has finished running. This means that if the run() method has an endless loop (let's say it's waiting for incoming requests), then the main() method will never continue running, even if there are more lines of code after the call to run().
Calling aThread.start() creates a new actual thread (represented by the object aThread), makes the new thread call the run() method, and returns execution of the original thread to the next line in the main(). This means that the new thread can run around in circles forever, but it doesn't stop the main() code from creating more threads or performing other tasks.
It will just run like you're calling a normal method. So the method will be running in the same thread that calls the method.
It will run in the current Thread not in new Thread So If you call run method yourself it is meaningless. Because It doesn't create a new Thread.
If you call the start-method on a Thread class, the start-method will return after a while, but in concurrency will run the content of the run-method. If you call the run-method directly it will be executed and return to the caller, after the method is completely done - as every normal method call.