Thread as constructor or run() - java

Is there any difference between creating a thread using the run() method as opposed to using the a constructor?
I noticed that I can start the thread and it acts the same in both ways.
new Thread MyThread().start
For example, as a constructor:
public class MyThread extends Thread{
public MyThread(){
// Do something
}
}
or as the run() method
public class MyThread extends Thread{
public void run(){
// Do something
}
}
Is there any difference between constructor or run()? Thanks!

It does not act the same in both cases
These cases are entirely different.
First, you probably need to learn about Threads and non-blocking processes. A Thread is used to do something asynchronously. So if you wanted to do some background task whilst doing something else then you would use a Thread. A good example is a GUI; you need one Thread to listen for GUI events (mouse clicks, button presses) and another to do any long running processing.
Now, onto your examples.
In Java a Thread consists of a run method that executes asynchronously when the start method is called. So when overriding Thread you change the run method. In reality you should never override Thread, you should use the constructor that takes a Runnable. There are many reasons for this, you should read up on concurrency.
Any code you place in your Thread constructor will be executed in the Thread that calls your constructor so this is not called asynchronously.

If you put the code in the run method, a new thread will be started upon invocation of start, which uses the run method as its starting point. If you put the code in the constructor, however, it will be run in the same thread as that which invoked the constructor, because a constructor is a special case of a method. Thus, if you want to start something in a new thread, put it in run, otherwise, put it in the constructor. Also, if you want to start a thread, never call Thread.run, because of the same reason not to put code in the constructor. Always call Thread.start().

The key difference is this:
The code in your constructor is executed immediately and synchronously when the constructor is invoked.
The program will stop and wait for that code to complete before moving on to the next line of code.
If you put the code inside run() method AND use Thread.start(), the code will be executed in a separate thread (i.e. it will run asynchronously).
Your program will continue to execute (moving to the next line of code immediately) while the code in your run() method runs in parallel.
This is helpful if the code in run() takes a very long time to execute.
That's because your program can continue to do other things while it waits for the thread to finish its work.

There is a difference. The constructor that creates the Runnable or subclass thereof runs in the main thread.
When starting a thread using:
new Thread(myRunnable).start();
you'll actually have run( of myRunnable run in the new thread.
NB You'll want to have a reference to the thread object in many cases. This code example is merely illustrative
On another note, never, ever, ever, give a thread this if starting within a constructor. Your computer could explode, or asphyxiation, drowning, or poisoning may occur.

Related

Java Thread only works once [duplicate]

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

Method Not Executing in a Synchronous Manner

I have a MVC-based Java application which I am building, and there is a particular method within my controller (shown below) which behaves as follows:
The model is updated via the initialize method, as I would intend.
The update to the view is not occurring because the model.start() method never terminates (since it is an infinite while loop).
I want to have my view to update first, and then be able to start() my model. How do I alter my code to get the desired behavior?
I suppose one workaround would be replace the model.start() line with code that fires an event which my model is able to observe, but I have not tried that yet, because I want to understand the source of my problem.
Also, I have no idea if this is relevant, but my main application class defines a separate thread for my swing components via SwingUtilities.invokeLater(new Runnable()..., and my view is made up of swing components. There may be some issue related to multiple threads executing, and if so, that would explain why my initializedPerformed() method is not executing in a synchronous way.
Method in the controller which does not behave like I expect/want:
public void initializePerformed(Event e) {
model.initialize(e);
view.getPanel().setName(model.getName());
model.start();
}
model.start():
public void start() {
while (true) {
}
}
If you need model.start() at all, which I highly doubt you do, then start it in a separate thread like this:
new Thread() {
public void run() {
model.start();
}
}
If model is actually inheriting from Thread, then you shouldn't be overriding start() at all. You should override run(), which is called after Thread.start(), and after the new thread has actually been created. If you override start(), no new threads will be created.
From what I remember about swing, all operations must be done by the "main" app thread (I forgot the technical name of it).
The pattern is : create threads to process your data, and leave the main thread only for display. When there is an event that should be displayed, notify the view but let the main thread change it (typically use the semaphore pattern, but if you find it too complex, you can also have an infinite loop that looks what's new each 100 ms for example and calls wait() to check again: business threads will change variables accessible to the main thread.
Best Regards,
Zied Hamdi
http://1vu.fr

Running a thread more than once

I have a Thread which runs my game loop. I want to be able to run this game loop each time I start a new game. But since the threads in Java can only be started once, how can I do this?
Create a new Thread around the same Runnable instance and start that.
Since you want the Thread that runs the game loop to keep running it, you need to code it something like this:
public class GameLoop implements Runnable {
...
public void run() {
while (gameNotFinished) {
// do stuff
}
}
}
If that is not working, then the chances are that the run() method is dying because of an exception that you are not catching / logging, and therefore not noticing.
1. When you say that "you need to run a thread", i means you want to start a sub-task on a separate thread.
2. Now if you mean this certain sub-task, then please prefer to run a new thread.
3. As you said But since the threads in Java can only be started once
This means that when a thread (thread of execution) completes its run() method, then the Thread object associated with it permanently looses its threadness, right....
But if this thread is from a pool, then the pool itself manages the Thread objects and its reused. Try using Executors from java.util.concurrent package.
1) The short answer is precisely what SLaks already said: just "...create a new thread around the same runnable instance and start that."
2) I think you might be confused about the distinction between the everyday meaning of "start", and the semantics of the Java Thread method "start()". This tutorial might help:
http://www.geom.uiuc.edu/~daeron/docs/javaguide/java/threads/states.html
3) Should you wish to re-use the same thread, you can use the methods "wait()" and "resume()":
http://www.javabeginner.com/learn-java/java-threads-tutorial

Android Thread details

I can create a class which extends Thread and overrides the run method with a loop.
I then start it with myThread.start(), which create the OS thread and executes my run().
That's all good.
However, I don't quite understand the details. I'll have a go at working this out using test code when I get the chance, but before then can anyone answer these:
Q1. When does the constructor get executed, presumably when myThread is declared, or on start()?
Q2. What happens when my run() code completes? Is there a way of getting it to run again in the same thread (i.e. not losing all the thread variable values defined in class) Presumably calling start() might create a new os thread?
Q3. Presumably just calling myThread.run() would execute my run() in the context of the current activity, not mythread, in which case how could it access the thread variables?)
-Frink
A1) When you construct the instance of your MyThread class
A2) Threads cannot be run twice or restarted, as stated in the documentation.
A3) Yes, calling run() directly will execute that function in the current Thread, not in a new Thread. It doesn't make much sense to create a class that extends Thread if you want to just call run(). You should always call start().

what does happen if I call run() method myself?

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.

Categories