I've been using threads for 2-3 days now, and I've got a quick question regarding methods. I'm making an Android application and it starts off with the main UI thread (let's call it the "UI Thread" for clarity). I'm spawning a new thread using the following code:
Thread thread = new Thread(new Runnable() {
#Override
public void run() {
someMethod();
}
});
thread.start();
My question is, will someMethod() also run on the new thread that I just created because I'm calling it from there? Or will it run on the UI thread? For reference, someMethod() is located outside outside of the method that's creating the new thread.
If someMethod() won't run on the new thread, how do I make it do so? Thanks.
will someMethod() also run on the new thread that I just created because I'm calling it from there?
Yes, that is exactly what happens. The method is just code. It's independent of the thread-of-control that happens to be running in it at a given point and time. This also means that there could be multiple threads executing that code at any given point in time if there are multiple cpu/cores.
You should take a look at Callable<V> and Future<T>, there you can call methods, that are not processed on the calling thread. You shouldn't work with threads anyway nowadays.
There are more modern approaches available.
Here is a link that should give you an idea http://www.vogella.com/articles/JavaConcurrency/article.html#futures
All of the actions taken by run, including calling someMethod, stay on the new Thread unless that code tells Java to run something in another thread (like with invokeLater or by using an Executor).
Related
According to the StackOverflow answers, start() creates a thread and executes the code in this new thread and run() executes the code in the current thread without creating any - as if it was a Runnable
But the docs, if I understood them properly, say that start() initializes a new thread an then, if you want to re-execute your code in the same thread, you call run()
Which one is right?
UPD
Okay, looks like calling run() manually is not a good practice and is at least useless. Are there some good ways to call the code in run()? Say, I have a relatively slow action that is required frequently, one instance at a time - what then?
As quoted, neither of them is right.
start doesn't create or initialize a thread. It starts a thread. From the documentation:
Causes this thread to begin execution; the Java Virtual Machine calls the run method of this thread.
The thread is created and initialized by calling the Thread constructor, which naturally you have to do prior to calling start. (That's the "external myth," anyway; I'd have to check the JVM spec, but I suspect it would probably be valid for a JVM to defer actual creation of the OS thread until/unless you called start.)
In the normal case, you never call the run method of a Thread instance directly. Instead, you start the thread via start and the JVM schedules a call to run on the actual thread assigned to that Thread instance. If you call run directly, it gets called on the thread you're using to do that, which probably isn't the one assigned to the Thread instance.
You may find the Java concurrency tutorial useful.
Re your comment below:
And how to re-execute the code in run()? Restart the thread or have some infinite loop with a boolean value controlling the execution?
The latter, but not an infinite loop, a loop with a termination condition. From the start 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.
So once run returns, that's it, you can't keep using the thread. Instead, you have the thread not return from run until its work is done. If you want to keep it around waiting for work, it should wait on a semaphore of some kind that you can signal from outside the thread, to wake it up to do some work.
A subsection of the tutorial above talks about one way to do that with Guarded Blocks using wait and notify/notifyAll.
Here's a simple example where every call to System.out.println prints the name of the thread on which the call was made so you can see which thread does what:
Live Copy
class Example
{
public static void main (String[] args) throws java.lang.Exception
{
Thread t= new Thread(new Runnable() {
#Override
public void run() {
System.out.println(Thread.currentThread().getName() + ": Running run");
}
});
System.out.println(Thread.currentThread().getName() + ": Running main");
System.out.println(Thread.currentThread().getName() + ": Calling t.start()");
t.start();
System.out.println(Thread.currentThread().getName() + ": Calling t.join() to wait for thread exit");
try {
t.join();
} catch (InterruptedException ie) {
System.out.println(Thread.currentThread().getName() + ": Calling got InterruptedException");
}
System.out.println(Thread.currentThread().getName() + ": Program complete");
}
}
Example output:
main: Running main
main: Calling t.start()
main: Calling t.join() to wait for thread exit
Thread-0: Running run
main: Program complete
Note that our main thread just called start; then the JVM set things up so that run would be called on the thread we'd created.
Your confusion probably comes from the ambigous use of the terms thread, create and initialize. Without specifying what they exactly address its easy to misunderstand, because there are multiple concepts that the term thread is used to describe.
On one hand, there is the Thread object (that is created through new Thread(...) constructor). Thats not the thread in terms of actually executing anything. Its just a facade for the threading mechanism that implements a standardized API to interact with the OS/VM.
Just creating a Thread instance is basically not any different from creating any other java object. Nothing happens yet that has anything to do with actually adding a thread to the OS thread scheduler.
The thread on the OS side is actually created in a (private) native method start0(), the start() method performs some sanity checking, then calls start0() to actually create an OS-Level thread.
So the general order of actions is:
Create and Initialize a Thread-Object
Nothing out of the ordinary happens yet
You invoke start() on above Thread-Object
Delegates to native code to create an OS-Level thread. Entry point for the OS-Level thread is Thread.run() on the java side.
Executes Thread.run() on the new thread (default implementation of run delegates to the Runnable the Thread object was created with, or does nothing if no Runnable)
if I understood them properly, say that start() initializes a new thread an then, if you want to re-execute your code in the same thread, you call run()
This is incorrect. You need to understand that every Java program begins it's execution with the main thread. In other words, when you run a Java program that has a main method (e.g java MyProgram), a new execution stack is created with the main method at the bottom of this stack.
If a program creates a Thread instance in the main method and calls the start method on the thread instance, a new execution stack will be created with the run method at the bottom of the stack. You will now have two execution stacks. One with the main method at the bottom of the stack and the other with the run method at the bottom of the stack. These two stacks can complete their execution in parallel.
On the other hand, If you call run on a thread instance in the main method instead, it will simply be called in the same execution stack as the main method. A new execution stack will not be created. Therefore, calling run on a thread instance is as good as calling any other method on any other object and has no special meaning.
Here is the main difference between start() and run():
Thread#start: when program calls start() method the Java Virtual Machine calls the run method of this thread.
Thread#run: If you call run() method directly code inside run() will execute on current Thread.
Folks,
I know this question has been asked before here, though indirectly. But it didn't answer my doubt.
Question : Is it legal to call the start method twice on the same Thread?
From the 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.
I agree. But my code doesn't throw a IllegalThreadStateException which it is expected to throw on execution of following program.
public class Tester extends Thread {
public void run() {
System.out.print("run");
}
public static void main(String[] args) {
Tester thread = new Tester();
new Thread(thread).start();
new Thread(thread).start();
}
}
Q.1) I ran the above code in Eclipse. Here, since I am trying to start a new thread on the same instance, a IllegalThreadStateException is expected to be thrown. But it doesn't.
Why ?
Q.2) If at all we did start a new thread on the same instance, what harm it would do ?
Any help would be greatly appreciated !
You are NOT calling start() on the same instance. Everytime you use new you are creating a distinct instance. Hence no problem calling start().
If you did this:
Thread t = new Thread(thread);
t.start();
t.start();
Then you may have a problem.
Firstly, you are invoking on two different thread objects ie:
new Thread(thread).start();
new Thread(thread).start();
you are calling start method on two different instances. for which reason you are not getting the exception.
try with following to get the exception
thread.start();
thread.start();
For your second question. you can get the answer here : Why can't we call the start method twice on a same instance of the Thread object?
which is fortunately asked by me :)
Can java thread invoke start more than once ?
You can involve start() as often as you like. However you will get an IllegalThreadStateException if you call it more than once on the same Thread.
Q.1) I ran the above code in Eclipse. Here, since I am trying to start a new thread on the same instance, a IllegalThreadStateException is expected to be thrown. But it doesn't.
Thats because you created three different threads. One is the Tester and two wrap the Tester.
Q.2) If at all we did start a new thread on the same instance, what harm it would do ?
Other than create confusion, none. You shouldn't do this. Instead the Tester should implement Runnable.
Q.1) I ran the above code in Eclipse. Here, since I am trying to start a new thread on the same instance, a IllegalThreadStateException is expected to be thrown. But it doesn't.
You are not caling start() on same instance.
new Thread(thread).start();
the above statement is same as
new Thread((Runnable)thread).start();
As most of all answers covered Q1, Here i would like to concentrate on Q2 which is " If at all we did start a new thread on the same instance, what harm it would do ?"
first point to consider is when do you want want to call the thread start method second time,is it when the first thread is executing(case:1) or else after the execution of first thread is done(case 2)
case1 : To identify the thread which is started and executing the only way we have is thread object which is used for creation, so IF there was a chance to call the start() method second time there would be for suppose other thread getting created and it executes, but if we want to change/manipulate a particular thread of the multiple threads which are executed on a particular instance how would we identify them individually,so it would be totally impossible and so to identify a running thread uniquely and work on it java didn't allow to call start() method multiple times .
case 2:why didn't java allow us to call start() method multiple times if already running thread is finished?
in java once the scope of the object is ended it need to be garbage collected,so in case of thread objects also this happen,but if there is a facility to call start method multiple times the java env should not allow GC to takes place on thread object thinking that there may be a second time to use this thread object and this thread object will forever be in heap(or some place) without getting GC.
so considering above two reasons they might have made restrictions on calling start() method on a thread object only once.
And here we see why the Executors make so much sense.
Typical idiomatic Java would say that you shouldn't run your own threads much at all; create an executor service, and let it manage the threads. You just create Runnable instances and pass those to the executor service; you can call Runnable's run() method as often as you like, whenever and wherever it makes sense to do so, and you don't have to concern yourself with Thread management at that point.
Extending Thread is also a one-shot deal; extending superclasses in Java is expensive (since you get ONE superclass, that's it). However, you can extend as many interfaces as you like, so Runnable gives you a more powerful object hierarchy as well.
This is a Java syntax question, but just for some background.
Using android, I created a small app that went really slow and often crashed because when a button was clicked the onClick() method changed button images for various buttons. It was really clunky and slow and I found out after a search on the net that the problem is pretty common, and when changing lots of images in the onClick() method, its best to put them in a separate thread. And some kind person gave the code for doing this.
new Thread(new Runnable() {
public void run() {
quest.post(new Runnable() {
public void run() {
correct = nextQ();
}
});
}
}).start();
The nextQ() method and the "quest" TextView are mine. It's not really relevant to my question what they do, but nextQ does a database search and updates images, and running it outside the thread is really slow and crashy.
Now I copied and pasted this code into my code and it runs fine. A happy ending. But I dont feel comfortable using code I don't understand. And I don't know Java very well. SO I researched as best I could anonymous inner classes, but I'm still stumped by the code.
So the anonymous class extends thread, and as it's argument uses an anonymous class, implementing runnable, in which the "meat" of the code is placed..
Questions:
1)Why would I do this? I can understand using thread OR runnable, but why together?
2)How does this work? I went back to basics of thread and runnable, but I don't see how you use them together this way.
you are creating an anonymous implementation of the Runnable interface
you are passing that implementation to the constructor of the Thread class. So you are not extending Thread, you are just instantiating it, and pass an argument.
you then start() the thread. Thus the run() method of the passed argument will be invoked in a new thread.
You need to do this, because:
the Runnable defines what gets executed
the Thread actually executes it.
Your confusion is understandable, since a Thread is also Runnable. That's why in Java 5 the executors framework was introduces, which separated the execution mechanism (an executor) from the executed code (Runnable or Callable).
So the anonymous class extends thread,
No it does not. It implements Runnable.
1)Why would I do this? I can understand using thread OR runnable, but why together?
If you use Runnable, you still need to run it somehow, and one way to do that is to create a new Thread and give it to Runnable (which is what is being done here).
2)How does this work?
new Thread(runnable) creates a new Thread, which you can then start(). It will execute the code in the Runnable's run() method.
Runnable contains the code that should be executed (an alternative is Callable).
Thread controls how and when the code is executed (alternatives are ExecutorService or calling run() directly for synchronous execution on the current Thread)
In general (and to keep these two functions apart), you do not want to extend Thread, you only want to implement Runnable or Callable.
It is possible to extend Thread and directly implement run (rather than letting it delegate to the Runnable), but that is sort of old school. If they were to redesign the Java API today, Thread would probably not implement Runnable anymore. Thread is more of a Runner than it is a Runnable.
Or is it?
I have a thread object from:
Thread myThread = new Thread(pObject);
Where pObject is an object of a class implementing the Runnable interface and then I have the start method called on the thread object like so:
myThread.start();
Now, my understanding is that when start() is called, the JVM implicitly (and immediately) calls the run() method which may be overridden (as it is in my case)
However, in my case, it appears that the start() method is not called immediately (as desired) but until the other statements/methods are completed from the calling block i.e. if I had a method after the start() call like so:
myThread.start();
doSomethingElse();
doSomthingElse() gets executed before the run() method is run at all.
Perhaps I am wrong with the initial premise that run() is always called right after the start() is called. Please help! The desired again is making executing run() right after start(). Thanks.
Um... the run() method will run in a different thread. That, per definition, means you cannot make any assumptions about before or after which statements in the current thread it will execute, unless you synchronize them explicitly.
Now, my understanding is that when start() is called, the JVM implicitly (and immediately) calls the run() method ...
That is incorrect. It does implicitly call run(), but the call does not necessarily happen immediately.
The reality is that the new thread becomes available to be scheduled at some point in time after the start() call is made. The actual scheduling is up to the native scheduler. It could happen immediately, or the parent thread could continue for a period before the child thread is scheduled.
To force your thread to start running immediately (or to be more accurate, to start running before doSomethingElse()), you need to do some explicit synchronization; e.g. something like this:
java.util.concurrent.CountDownLatch latch = new CountdownLatch(1);
new Thread(new MyRunnable(latch)).start();
latch.await(); // waits until released by the child thread.
doSomethingElse();
where
class MyRunnable implements Runnable {
private CountDownLatch latch;
MyRunnable (CountDownLatch latch) { this.latch = latch; }
public void run() {
doSomeStuff();
latch.countDown(); // releases the parent thread
doSomeMoreStuff();
}
...
}
There are other ways to implement the synchronization using the concurrency classes, or Java's mutex / wait / notify primitives1. But explicit synchronization between the two threads is the only way to guarantee the behavior that you require.
Note that the doSomething() call in the child thread will complete before the parent thread is released, but we can say nothing about the order of execution of doSomethingElese() and doSomeMoreStuff(). (One might run before the other and vice versa, or they might run in parallel.)
1 - Using wait / notify is not recommended, but it may be your only option if the concurrency APIs are not available; e.g. on Java ME.
run() is the first thing within your code that the new thread does, but there's some set-up work that the new thread does first, and there's no guarantee that any significant amount of work will by done by the new thread before the original thread goes on to call doSomethingElse().
You're right in thinking that there are no guarantees here. Making assumptions about the behaviour of multithreaded code is the source of much pain - try not to do it!
When you call myThread.start(), your thread becomes available for execution. Whether it will actually gain CPU, and for how long -- it's up the the OS scheduler. In fact, your run() may be getting control immediately, but losing it before it can do anything you can notice. The only way to ensure that your thread executes what you need before doSomethingElse() is to use explicit synchronization.
You've started a new thread. That thread runs in parallel to the thread that started it so the order could be:
pObject.run();
doSomethingElse();
or
doSomethingElse();
pObject.run();
or, more likely, there will be some crossover. pObject.run() may run in the middle of doSomethingElse() or vice versa or one will start before the other finishes and so on. It's important to understand this and understand what is meant by an atomic operation or you will find yourself with some really hard-to-find bugs.
It's even more complicated if two or more threads access the same variables. The value in one may never be updated in one thread under certain circumstances.
I highly suggest:
You don't make your program multi-threaded unless you absolutely need to; and
If you do, buy and read from cover to cover Brian Goetz's Java Concurrency in Practice.
calling the start method on a Thread Object may not make the jvm invoke the run() method immidiately, rather it makes the thread a runnable and ready for execution, in this case the parent thread first executes its code and then passes control to the child thread, if u want the child thread to execute before the parent thread code is executed use the chileThreadObject.join() method in the parent thread.
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