This question already has answers here:
When would you call java's thread.run() instead of thread.start()?
(14 answers)
Closed 8 years ago.
I learned that to start a thread the recommended way is to invoke start() method on thread object. But this in turn invokes the run() method. So why not directly invoke run() method?
Here's what I tried but I fail to bring any conclusion :
public class Tester {
public static void main (String[] args) {
Runner r = new Runner();
Thread t1 = new Thread(r, "Thread A(runnable)");
Thread t2 = new Thread(r, "Thread B(runnable)");
Thread s1 = new Strider("Thread C");
Thread s2 = new Strider("Thread D");
t1.run(); // t1.start();
t2.run(); // t2.start();
s1.run(); // s1.start();
s2.run(); // s2.start();
}
}
class Runner implements Runnable {
private int counter;
public void run() {
try {
for (int i = 0; i != 2; i++) {
System.out.println(Thread.currentThread().getName() + " Runnable: "
+ counter++);
Thread.sleep(1000);
}
}
catch(InterruptedException e) {
e.printStackTrace();
}
}
}
class Strider extends Thread {
private int counter;
Strider(String name) {
super(name);
}
public void run() {
try {
for (int i = 0; i != 2; i++) {
System.out.println(Thread.currentThread().getName() + ": "
+ counter++);
Thread.sleep(1000);
}
}
catch(InterruptedException e) {
e.printStackTrace();
}
}
}
OUTPUT (using start()) : varies
Thread A(runnable): 0
Thread C: 0
Thread B(runnable): 1
Thread D: 0
Thread B(runnable): 3
Thread D: 1
Thread A(runnable): 2
Thread C: 1
OUTPUT (using run()) : always remains same
main Runnable: 0
main Runnable: 1
main Runnable: 2
main Runnable: 3
main: 0
main: 1
main: 0
main: 1
Also kindly provide your opinion on why not to use run() directly ?
Calling the run method directly does not start the thread but is a synchronous call like any other method call in Java. Hence the output remains always the same.
Only when you call the start method, actual Java infrastructure is involved and a new thread is created, which then calls the run method.
If you call the run method explicitly, no new thread is going to be
started. Calling run() directly just executes the code synchronously
(in the same thread), just like a normal method call.
The Thread class' run() method does nothing, so sub-classes should override the method with code to execute in the second thread. If a Thread is instantiated with a Runnable argument, the thread's run() method executes the run() method of the Runnable object in the new thread instead.
Depending on the nature of your threaded program, calling the Thread run() method directly can give the same output as calling via the start() method, but in the latter case the code is actually executed in a new thread.
Related
I'm a Java learner, trying to understand Threads.
I was expecting output from my program below, in the order
Thread started Run Method Bye
But I get output in the order
Bye Thread started Run Method
Here is my code:
public class RunnableThread
{
public static void main(String[] args)
{
MyThread t1= new MyThread("Thread started");
Thread firstThread= new Thread(t1);
firstThread.start();
System.out.println("Bye");
}
}
class MyThread implements Runnable
{
Thread t;
String s= null;
MyThread(String str)
{
s=str;
}
public void run()
{
System.out.println(s);
System.out.println("Run Method");
}
}
In a multithreaded code there's no guarantee which thread will run in what order. That's in the core of multithreading and not restricted to Java. You may get the order t1, t2, t3 one time, t3, t1, t2 on another etc.
In your case there are 2 threads. One is main thread and the other one is firstThread. It's not determined which will execute first.
This is the whole point of Threads - they run simultaneously (if your processor has only one core though, it's pseudo-simultaneous, but to programmer there is no difference).
When you call Thread.start() method on a Thread object it's similar (but not the same, as it's starting a thread, and not a process and former is much more resource consuming) simultaneously starting another java program. So firstThread.start() starts to run paralel to your main thread (which was launched by your main method).
This line starts a main execution thread (like a zeroThread)
public static void main(String[] args)
Which you can reference, by calling Thread.sleep() for example.
This line
firstThread.start();
Starts another thread, but in order to reference it you use it's name, but you reference it from the main thread, which is running paralel to firstThread.
In order to get the expected output you can join these two threads, which is like chaining them:
This way:
public static void main(String[] args)
{
MyThread t1= new MyThread("Thread started");
Thread firstThread= new Thread(t1);
firstThread.start();
firstThread.join();
System.out.println("Bye");
}
join(), called on firstThread (by main thread) forces main thread to wait until the firstThread is finished running (it will suspend proceding to the next command, which is System.out.println("Bye");).
It appears that you seek the thread (and probably more than one) to run while main() waits for everything to finish up. The ExecutorService provides a nice way to manage this -- including the ability to bail out after a time threshold.
import java.util.concurrent.*;
class MyThread implements Runnable { // ... }
class MyProgram {
public static void main(String[] args)
{
MyThread t1 = new MyThread();
MyThread t2 = new MyThread();
MyThread t3 = new MyThread();
// At this point, 3 threads teed up but not running yet
ExecutorService es = Executors.newCachedThreadPool();
es.execute(t1);
es.execute(t2);
es.execute(t3);
// All three threads now running async
// Allow all threads to run to completion ("orderly shutdown")
es.shutdown();
// Wait for them all to end, up to 60 minutes. If they do not
// finish before then, the function will unblock and return false:
boolean finshed = es.awaitTermination(60, TimeUnit.MINUTES);
System.out.println("Bye");
}
}
There is no specified order in which Java threads are accustomed to run. This applies for all threads including the "main" thread.
If you really want to see it working, try:
class RunnableThread
{
public static void main(String[] args)
{
MyThread t1= new MyThread();
Thread firstThread= new Thread(t1);
firstThread.start();
System.out.println("Thread Main");
for(int i=1;i<=5;i++)
{
System.out.println("From thread Main i = " + i);
}
System.out.println("Exit from Main");
}
}
class MyThread implements Runnable
{
public void run()
{
System.out.println("Thread MyThread");
for(int i=1;i<=5;i++)
{
System.out.println("From thread MyThread i = " + i);
}
System.out.println("Exit from MyThread");
}
}
When You start a Thread it will execute in parallel to the current one, so there's no guarantee about execution order.
Try something along the lines:
public class RunnableThread {
static class MyThread implements Runnable {
Thread t;
String s= null;
MyThread(String str) {
s=str;
}
public void run() {
System.out.println(s);
System.out.println("Run Method");
}
}
public static void main(String[] args) {
MyThread t1= new MyThread("Thread started");
Thread firstThread= new Thread(t1);
firstThread.start();
boolean joined = false;
while (!joined)
try {
firstThread.join();
joined = true;
} catch (InterruptedException e) {}
System.out.println("Bye");
}
}
This is not a thread start order problem. Since you're really only starting a single thread.
This is really more of an API Call speed issue.
Basically, you have a single println() printing "bye", which gets called as soon as the Thread.start() returns. Thread.start() returns immediately after being called. Not waiting for the run() call to be completed.
So you're racing "println" and thread initializaiton after "thread.start()", and println is winning.
As a sidenote, and in general, you might want to try to use ExecutorService and Callable when you can, as these are higher level, newer APIs.
Here is an example that creates a new thread and starts it running:
class NewThread implements Runnable {
Thread t;
NewThread() {
// Create a new, second thread
t = new Thread(this, "Demo Thread");
System.out.println("Child thread: " + t);
t.start(); // Start the thread
}
// This is the entry point for the second thread.
public void run() {
try {
for(int i = 5; i > 0; i--) {
System.out.println("Child Thread: " + i);
Thread.sleep(500);
}
} catch (InterruptedException e) {
System.out.println("Child interrupted.");
}
System.out.println("Exiting child thread.");
}
}
Now consider the other thread(main),
After the new thread is created, it will not start running until you call its start( ) method,
which is declared within Thread. In essence, start( ) executes a call to run( ).
public class ThreadDemo {
public static void main(String args[]) {
new NewThread(); // create a new thread
try {
for (int i = 5; i > 0; i--) {
System.out.println("Main Thread: " + i);
Thread.sleep(10000);
}
} catch (InterruptedException e) {
System.out.println("Main thread interrupted.");
}
System.out.println("Main thread exiting.");
}
}
Inside NewThread’s constructor, a new Thread object is created by the following statement:
t = new Thread(this, "Demo Thread");
Passing this as the first argument indicates that you want the new thread to call the run( )
method on this object.
Next, start( ) is called, which starts the thread of execution beginning at the run( ) method.
This causes the child thread’s for loop to begin.
After calling start( ), NewThread’s constructor returns to main( ).
When the main thread resumes, it enters its for loop.
Both threads continue running, sharing the CPU, until their loops finish.
After calling start( ), why does the thread’s constructor returns to main( ), without being the control forwarded to the run() method?
start() starts a new thread. The control of that new thread reaches your run() method. Your expectation for the control in the thread which executed start() to reach run() is illogical and, if it were met, would be self-defeating.
Read the Javadoc of Thread.start:
Causes this thread to begin execution; the Java Virtual Machine calls the run method of this thread.
The result is that two threads are running concurrently: the current thread (which returns from the call to the start method) and the other thread (which executes its run method).
The difference between the start() and run() methods is that the first one creates a new thread and this newly created thread will internally execute the run method. Once the new thread is created, control is returned to the caller thread to continue and the result is that two threads running in parallel.
On the other hand, calling run will simply execute the method in the same thread (no new thread is created).
I found this code on a tutorial website:
class NewThread implements Runnable {
Thread t;
NewThread() {
// Create a new, second thread
t = new Thread(this, "Demo Thread");
System.out.println("Child thread: " + t);
t.start(); // Start the thread
}
// This is the entry point for the second thread.
public void run() {
try {
for(int i = 5; i > 0; i--) {
System.out.println("Child Thread: " + i);
// Let the thread sleep for a while.
Thread.sleep(50);
}
} catch (InterruptedException e) {
System.out.println("Child interrupted.");
}
System.out.println("Exiting child thread.");
}
}
public class ThreadDemo {
public static void main(String args[]) {
new NewThread(); // create a new thread
try {
for(int i = 5; i > 0; i--) {
System.out.println("Main Thread: " + i);
Thread.sleep(100);
}
} catch (InterruptedException e) {
System.out.println("Main thread interrupted.");
}
System.out.println("Main thread exiting.");
}
}
In the following line, what is the purpose of the arguments, and what is the meaning of this in the first argument:
t = new Thread(this, "Demo Thread");
Also, what is the expected behaviour (flow) of this code?
When creating a new Thread object you must pass in a Runnable object (which does the actual work in its run() method) as the first argument to the constructor. The second argument is a name for the thread. So, in your code, the following line in the NewThread class constructor:
t = new Thread(this, "Demo Thread");
Creates a new Thread object t named Demo Thread using itself (an instance of NewThread) as the Runnable task, since it implements the Runnable interface. Then, when t.start() is called, the run() method of the NewThread instance t is called.
The API documentation for java.lang.Thread and java.lang.Runnable give more details.
So, your code creates a NewThread object, which starts a child thread in the constructor running the Child Thread loop, and the Main Thread loop is executed by the rest of the code in your main() method. I would expect to see output from the child thread interleaved with output from the main thread when this is run.
Also, when catching InterruptedException and not re-throwing it, it is good practice to restore the interrupted status of the thread, something like this:
} catch (InterruptedException ie) {
System.out.println("Interrupted: " + ie.getMessage());
Thread.currentThread().interrupt();
}
This tutorial by Brian Goetz is very good if you want to learn more about Java threading. It's part of an IBM developerWorks Java concurrency training module.
The line t = new Thread(this, "Demo Thread") is creating a new thread passing the instance of java.lang.Runnable that the thread should execute and the name to give the thread (commonly used during logging operations).
It's a bit weird to have the class implementing java.lang.Runnable create the thread itself. Take a look at the examples of how to use threads on the JavaDoc for java.lang.Thread.
The constructor used in t = new Thread(this, "Demo thread") allows to pass a target. The target must be a Runnable. The target's run() method will be invoked as a result of starting t, so the Thread is created and runs. See the documentation
That's some seriously messed up code up there. OP, you did not write this, but you'll take heat just for stumbling on it.
First of all: The NewThread is not a thread, it's a Runnable. Not the same thing, and for a reason. But then its constructor declares a new thread and starts it right away, turning the Runnable into some sort of a Zombie Thread, which defeats the whole purpose of having a Runnable in the first place, and is just a terrible idea, because if you wanted a Thread, you'd declare a Thread, not a Runnable. What if you want to use the Runnable in a ThreadPool? What if you want to define more than one of these Runnables and start them in a orderly fashion? What if the Runnable one day becomes a Callable, where would you see its Future?
Then, to add insult to injury, the code has concurrent code in the main thread. This servers no educational purpose, and has almost no real-life value, because in real life, you normally don't mix threaded code like that, you'd rather have one control thread (main) and 1..n worker threads (controlled by main).
The point of Threads and Runnables is to separate the functional description of the task (that's the Runnable) from the life-cycle behavior (that's the Thread). Parallel execution and scalability is a nice side benefit. So let's refactor the tutorial code to reflect that:
class Countdown implements Runnable {
public void run() {
try {
for(int i = 5; i > 0; i--) {
System.out.println("Child Thread: " + i);
Thread.sleep(50);
}
} catch (InterruptedException e) {
System.out.println("Child interrupted.");
}
System.out.println("Exiting child thread.");
}
}
public class ThreadDemo2 {
public static void main(String args[]) {
Thread t = new Thread(new Countdown());
t.start();
try {
for(int i = 5; i > 0; i--) {
System.out.println("Main Thread: " + i);
Thread.sleep(100);
}
} catch (InterruptedException e) {
System.out.println("Main thread interrupted.");
}
System.out.println("Main thread exiting.");
}
}
That's better. Now the Runnable does no longer pretend to be a Thread, nor does it even care about when or how or by whom it is going to be run. All it does is implement run() which does what the task is supposed to do, and the main thread gives this Runnable as a constructor argument to a new Thread and then start()s it, which in turn means the new Thread will call the Runnable's run(). But we can do better: the two threads do essentially the same thing, so we should implement them that way:
class Countdown implements Runnable {
final String name;
final int length;
final int skip;
public Countdown(String name, int length, int skip) {
this.name = name;
this.length = length;
this.skip = skip;
}
public void run() {
try {
for(int i = length; i > 0; i--) {
System.out.println(name + ": " + i);
Thread.sleep(skip);
}
} catch (InterruptedException e) {
System.out.println(name + " interrupted.");
}
System.out.println("Exiting " + name);
}
}
public class ThreadDemo3 {
public static void main(String args[]) {
Thread t1 = new Thread(new Countdown("Child One", 5, 50));
Thread t2 = new Thread(new Countdown("Child Two", 5, 100));
t1.start();
t2.start();
}
}
Now we have separated functionality from life-cycle management. Countdown is it's own class which does exactly what the name says and not more, and there is no more worker logic in main. Main just invokes countdowns and starts them.
OP, my biggest advice is: find a better tutorial. The Brian Goetz tutorial mentioned by grkvlt above is much better. You might want to invest some money on books by Goetz ("Java Concurrency in Practice") and Doug Lea ("Concurrent Programming in Java"), too.
Java Code:
// Create a second thread.
class NewThread implements Runnable
{
Thread t;
NewThread()
{
t = new Thread(this, "Demo Thread"); // Create a new, second thread
System.out.println("Child thread: " + t);
t.start(); // Start the thread
}
public void run() // This is the entry point for the second thread.
{
justCall();
}
public synchronized void justCall()
{
try
{
for(int i = 10; i > 0; i--)
{
System.out.println("Child Thread: " + i);
Thread.sleep(10000);
}
}
catch (Exception e)
{
System.out.println("Child interrupted.");
}
System.out.println("Exiting child thread.");
}
}
class ThreadDemo
{
public static void main(String args[])
{
NewThread nt = new NewThread(); // create a new thread
try
{
for(int i = 5; i > 0; i--)
{
System.out.println("Main Thread: " + i);
Thread.sleep(1000);
}
}
catch (InterruptedException e)
{
System.out.println("Main thread interrupted.");
}
System.out.println("Main thread exiting.");
}
}
here you can delete the synchronized justCall() method and you can initialize a synchronization block in a run() method(put justCall() method's code in a synchronized block).
How to synchronize child code here? Please Help. I read that Thread.sleep() method never releases the lock while it is executing in the synchronization block or method. But in my code main thread and child code executes concurrently. Please help to synchronize the child code using Thread.sleep() method.
When two threads synchronize on the same object, they will not both run that same code. This allows many different threads to cooperate running in many different areas of code at the same time.
A synchronized on a non-static method creates a lock on the this object. If it had been a static method the lock would have been on the Class object for the NewThread class. Any class and any instance of any class can have a syncronized on it and thus create a lock.
You have only one thread running in the synchronized area. So, while it is locked, no other thread is attempting to run the locked code. No other thread is attempting to synchronize on the nt instance of the NewThread class.
You might want to try doing this:
NewThread nt1 = new NewThread(); // create a new thread
NewThread nt2 = new NewThread(); // create a 2nd new thread
Then leave off the looping in the main class.
I want to restart a thread for some use, for example in the below code.
class Ex13 implements Runnable {
int i = 0;
public void run() {
System.out.println("Running " + ++i);
}
public static void main(String[] args) throws Exception {
Thread th1 = new Thread(new Ex13(), "th1");
th1.start();
//th1.join()
Thread th2 = new Thread(th1);
th2.start();
}
}
When I'm executing the above program , some time i'm getting the output as
Running 1
Running 2
and some time i'm getting only
Running 1
After few run i'm getting only
Running 1 as output.
I'm totally surprise about this behavior. Can any one help me understand this.
if I put the join() then i'm getting only Running 1.
You reuse Thread instance, not Runnable. Thread overwrites its run() method to
public void run() {
if (target != null) {
target.run();
}
}
Where target is the Runnable that you give to the constructor. besides that, Thread has an exit() method that is called by the VM, and this method sets target to null (the reason is this bug). So if your first thread has the chance to finish its execution, its run() method is pretty much empty. Adding th1.join() proves it.
If you want to keep some state, you need to keep reference to your Runnable instance, not the Thread. This way run() method will not be altered.
I don't know why do you need this, but (please note that this code doesn't ensure that th1 is ALWAYS executed before th2, though) :
public static class Ex13 implements Runnable {
AtomicInteger i = new AtomicInteger(0);
CountDownLatch latch;
Ex13(CountDownLatch latch) {
this.latch = latch;
}
public void run() {
System.out.println("Running " + i.incrementAndGet());
latch.countDown();
}
}
public static void main(String[] args) throws Exception {
CountDownLatch latch = new CountDownLatch(2);
Ex13 r = new Ex13(latch);
Thread th1 = new Thread(r, "th1");
th1.start();
Thread th2 = new Thread(r);
th2.start();
latch.await(); // wait until both theads are executed
System.out.println("Done");
}
You want the incrementing of i to be synchronized, i.e.
public class Ex13 implements Runnable {
int i=0;
public void run() {
System.out.println("Running "+ increment());
}
private synchronized int increment() {
return ++i;
}
}
The Java Tutorial has a very nice explanation of this given a very similar scenario. The problem is that incrementing a variable is not an atomic operation. Each thread needs to read the current state of i before setting it to the new value. Restricting access to incrementing the variable to one thread at a time assures you will get consistent behavior.
To see whats happening in the System.out.println you can also print the thread name:
Thread t = Thread.currentThread();
String name = t.getName();
System.out.println("name=" + name);
I see you call the two threads with the same runnable object, so they will both use the same "i" variable, in order for you to get Running 1 Running 2 you need to synchronize "i"