So I'm slightly confused as to how multi-threading works. For example, if I create a subclass of Thread called MySub, and this is what it looks like:
public class MySub extends Thread {
public void run {
for(int i = 0; i < 5; i++){
System.out.println(i);
}
}
}
And in the main class I do this:
public static void main(String[] args) {
Thread m = new MySub();
Thread m2 = new MySub();
m.start();
m2.start();
}
Shouldn't it call the start() method for m, and then go straight to calling the start() method for m2, without waiting for the m thread to finish? Isn't that the point of multithreading?
But in actuality, it prints 0 through 4 from the start() call for m, and then 0 through 4 for the start() call for m2. They didn't go concurrently, they went sequentially, which isn't what I expected. I kind of expected a mess of 0 through 4 numbers.
This is a race condition #Jake. Your main is not waiting for the first thread to finish before starting the second. It is starting the first thread which finishes its work before main gets a chance to start the second thread.
If you tried printing (let's say) 1000 numbers or something that takes more time, you would start to see them interleave. Or you could put a Thread.sleep(10) between your println statements which would show it more specifically.
FYI: it is recommended to have your classes implement Runnable as opposed to extends Thread. Then you would do:
Thread m1 = new Thread(new MySub());
m1.start();
Also, use of the ExecutorService code is recommended more than using thread directly.
Related
From what i read here Thread join on itself ;
When join method is called on itself, it should wait forever
I am currently preparing for ocajp 8 certification,for which going through dumps and when i got this question ,what i thought is main should wait forever
public class startinginconstructor extends Thread
{
private int x=2;
startinginconstructor()
{
start();
}
public static void main(String[] args) throws Exception
{
new startinginconstructor().makeitso();
}
public void makeitso() throws Exception
{
x=x-1;
System.out.println(Thread.currentThread().getName()+" about to call join ");
join();
System.out.println(Thread.currentThread().getName()+" makeitso completed ");
// above line shouldn't be executed (method shouldn't be completed as well )since it joined on itself..?
}
public void run()
{
System.out.println(Thread.currentThread().getName()+" run started ");
x*=2;
System.out.println(Thread.currentThread().getName()+" run about to complete ");
}
}
program ended with following output
main about to call join
Thread-0 run started
Thread-0 run about to complete
main makeitso completed
Did i wrongly get the meaning of thread waiting forever or is there something i am missing
note: I know starting thread from constructor is not a recommended practice.. this is exact question in the dumps so i just pasted it (* not pretty much exact actually,i have placed println statements to see flow of the program)
There is no thread that joins itself in your example.
The main() thread in your example creates a new thread and then it joins the new thread.
Don't confuse Thread (i.e., the java object) with thread (the execution of the code.) All of your methods belong to the same Thread object, but they run in two different threads.
James is correct (+1 from me), I'm just trying to make this more explicit. Here is what happens:
Your main thread constructs the startinginconstructor constructor.
The constructor calls start, which will result in the startinginconstructor object having its run method in the new thread.
After that the main thread will proceed to call makeitso. In makeitso this is the startinginconstructor object, so the result is that the main thread waits until the thread represented by the startinginconstructor object has finished.
Java objects can be called by any thread, just because an object extends Thread doesn't mean any invocation of that method is happening on that thread.
Below is my sample code, when my a.start() called it should create a thread and print "Run" immediately. But why does is called after printing "begin" 20 times.
How does thread "a" decide that it doesn't have to call run() immediately.
public class JoinTest implements Runnable {
public static void main(String[] args) throws InterruptedException {
Thread a = new Thread(new JoinTest());
a.start();
for (int i = 0; i < 20; i++) {
System.out.print("Begin");
}
Thread.sleep(1000);
a.join();
System.out.print("\nEnd");
}
public void run() {
System.out.print("\nRun");
}
}
Output:
BeginBeginBeginBeginBeginBeginBeginBeginBeginBeginBeginBeginBeginBeginBeginBeginBeginBeginBeginBegin
Run
End
I am little confused about the behavior of thread.
In my opinion "run" should be printed before "begin" because it get printed before the join() method is called, and at the time of join method called thread "a" must have finished its execution and calling join must be useless at that point.
Calling start() on a thread doesn't necessarily triggers the execution of its run() method immediately. Your thread is marked as started but the main thread pursues its execution into the for loop. Then the JVM is switching to your thread once the main thread reaches the sleep() statement.
You start the thread, then immediately do some printing, then sleep. Looking at your code I would actually expect to see Begin before Run because the thread is being started in the background, concurrently to your main thread going on with its work. Futhermore, the print method is synchronized so you repeatedly acquire that lock in a loop, giving even less chance to the second thread to interject.
I have tried your code with Thread.sleep eliminated, both with and without the join call. The behavior is the same in both cases: Run comes at the end most of the time and occasionally manages to get interleaved between the Begin words. Everything exactly as expected by the simple model of concurrency with synchronized blocks.
Here is a slight variation on your code which reliably prints Run before everything else, whether you call the join method or not. All that changed is the position of the sleep call.
public class JoinTest implements Runnable
{
public static void main(String[] args) throws InterruptedException {
Thread a = new Thread(new JoinTest());
a.start();
Thread.sleep(1000);
for (int i = 0; i < 20; i++) {
System.out.print("Begin");
}
a.join();
System.out.print("\nEnd");
}
public void run() {
System.out.print("\nRun");
}
}
The start() method calls the thread's run() method, although this takes a little time, which may just be enough for some or all of your 'Begin' loops to complete. When I run this on my machine the 'Run' output appears between the first and second 'Begin'. Try outputting with timestamps so you can see how long your machine is taking to execute each command:
public class JoinTest implements Runnable {
public static void main(String[] args) throws InterruptedException {
Thread a = new Thread(new JoinTest());
a.start();
for (int i = 0; i < 20; i++) {
System.out.println("Begin " + System.nanoTime());
}
Thread.sleep(1000);
a.join();
System.out.println("End " + System.nanoTime());
}
public void run() {
System.out.println("Run " + System.nanoTime());
}
}
Calling a.join() at that point ensures that you will always see 'Run' output before 'End', as join() waits for the thread to complete.
I have tried many scenarios with join(), "run" always get printed after "begin" but when i remove the join statement "run" always get printed before "begin". Why?
Because it's allowed. That's why. As soon as you call .start(), you have two threads. Untill your program calls a synchronization methods like .join() it's entirely up to the JVM implementation and the operating system to decide which thread gets to run when.
The a.join() call from your main thread forces the main thread to wait until the a thread has completed its run() method.
Without the a.join() call, the Java Language Specification permits the a thread to complete its work before a.start() returns in the main thread, and it permits the main thread to reach the end of the main() function before the a thread even begins to run, and it permits anything in between to happen.
It's entirely up to the JVM and the OS.
If you want to take control of the order in which things happen, then you have to use synchronized blocks, and synchronization objects and method (e.g., .join()).
But beware! The more you force things to happen in any particular order, the less benefit your program will get from using threads. It's best to design your program so that the threads can function independently of one another most of the time.
I have a simple test with thread:
package Thread;
class Sum extends Thread {
int low, up, S;
public Sum(int a, int b) {
low = a;
up = b;
S = 0;
System.out.println("This is Thread " + this.getId());
}
#Override
public void run() {
for (int i = low; i < up; i++) {
S += i;
}
System.out.println(this.getId() + ":" + S);
}
}
public class Tester {
public static void main(String agrs[]) {
Sum T1 = new Sum(1, 100);
T1.start();
Sum T2 = new Sum(10, 100);
T2.start();
System.out.println("Main process terminated");
}
}
but i don't understand when was run() method executed, it return same that:
This is Thread 8
This is Thread 9
Main process terminated
9:4905
8:4950
It's mean the run() method was executed after T1 and T2 start. I still think that when start() method was invoked the run() will be execute. Thank for advance!
When you call start() on the thread object , it invokes the run() method.
When in doubt , read the documentation: 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).
It is never legal to start a thread more than once. In particular, a thread may not be restarted once it has completed execution.
Suggested Reading:
Why we call Thread.start() method which in turns calls run method?
Oracle tutorial
Why is run() not immediately called when start() called on a thread object in java
The start() method creates a new thread, that executes the run() method.
From Documentation:
Causes this thread to begin execution; the Java Virtual
Machine calls the run method of this thread.
When we invoke Thread.start JVM creates a new native thread and then calls Thread.run which causes this Thread to begin execution. Thread.run is invoked by JVM asynchroneously, so these 3 lines
Main process terminated
9:4905
8:4950
might appear in any order.
The thread scheduler is selecting which thread for run. It can be random selection if you are not giving any priority for the thraed.
Here the thread scheduler will select thread and it will work in two separate stack space as two independent thread process. So thread T1 starts before thread T2 and there is no sleep, no wait, no join the both will give output at same time.
for more details please visit http://docs.oracle.com/javase/7/docs/api/java/lang/Thread.html#start%28%29
you can understand it more clearly if you use remaining functions of Thread like sleep(), join(), wait() etc...
In Java if I have a class that creates threads from the constructor (by calling some functions of that class) and I create an object of that class in my main method. Does the main method wait until all the threads are done or does it continue to the next line?
for example:
public static void main(String[] args) {
WorksWithThreads obj = new WorksWithThreads ( );
//does something else - does this line happen after all the 9 threads finished their job?
}
class WorksWithThreads(){
public WorksWithThreads(){
for(int i=0;i<9;i++)
WithThread tread= new WithThread();
}
private static class WithThread extends Thread {
public WithThread () {
run();
}
public void run(){
//does something
}
}
}
I hope I was not too confusing.. Thank you in advance..
Shiran
If you actually spawn new Threads your main method would continue right after finishing spawning (but before the threads end, assuming they run for sometime)
BUT you are not spawning threads. You are creating instances of the Thread class. To actually spawn new threads you'd have to call start. Calling run() as you do is just a normal method call and processing will only continue after it finished.
You might want to work through the official tutorial about this topic.
No. The very point of threads is that they don't halt execution of the thread that spawns them. main() will continue executing as soon as WorksWithThreads has finished spawning all its threads, but the threads it spawns will execute at the same time as the rest of main.
Yes it will run after the 9 threads are created.Here you have not even start those 9 threads.So before they are executed next line in main will be executed
As we know there is no provision to prevent more than one thread calling the run() method by using start() method. I did create two objects m1 and m2 both calling the same thread to run.
I need to make sure the first object finishes (m1.start) its execution by calling thread before second object execution starts.
My question is why can't i use synchronized keyword with run() method in the thread that I have created (i.e. MyThread1)?
I tried using "synchronized" to run() method in the thread that I have created but it gives arbitrary output (in other words m2 doesn't wait for the m1 to finish execution).
You can see at the very bottom of the program the output that I am getting.
public class ExtendedThreadDemo {
public static void main(String[] args) {
Mythread1 m1 =new Mythread1();
Mythread1 m2 =new Mythread1();
m1.start();
m2.start();
System.out.println(" main thread exiting ....");
}
}
MyThread
public class MyThread1 extends Thread {
public synchronized void run() {
for(int i=1; i<5; i++) {
System.out.println(" inside the mythread-1 i = "+ i);
System.out.println(" finish ");
if (i%2 == 0) {
try {
Thread.sleep(1000);
} catch(InterruptedException e) {
System.out.println(" the thread has been interrupted ");
}
}
}
}
}
Output
main thread exiting ....
inside the mythread-1 i = 1
finish
inside the mythread-1 i = 2
finish
inside the mythread-1 i = 1
finish
inside the mythread-1 i = 2
finish
inside the mythread-1 i = 3
finish
inside the mythread-1 i = 4
finish
inside the mythread-1 i = 3
finish
inside the mythread-1 i = 4
finish
As you can see after i = 2, second object (i.e. m2.start()) started executing.
Call m1.join() in main before calling m2.start().
Making methods synchronized only affects multiple calls to methods on the same object; m1 and m2 are different objects, so adding synchronized will have no effect.
This code snippet:
public synchronized void run() {
//code
}
is semantically equivalent to:
public void run() {
synchronized(this) {
//code
}
}
Note the this reference. This means that all synchronized blocks using the same this reference (lock object) are mutually exclusive. However you are creating two threads (objects), each is synchronizing on a different this reference.
There are several ways to improve your code:
Use only one Runnable and create two threads:
public class Mythread1 implements Runnable //...
and then:
Runnable r = new Mythread1();
Thread m1 = new Thread(r);
Mythread1 m2 = new Thread(r);
But this will only work if Mythread1 runnable is statelss as it will be shared by two threads.
Use the same lock instance
Pass some arbitrary lock object to both instances of Mythread1 and then use:
synchronized(lock) {
//code
}
Starting from Java 5 there are much more sophisticated ways of synchronizing code, but this one is fine for simple cases.
Use Thread.join()
You can call:
m1.start();
m1.join();
m2.start();
This will do the trick.
A synchronized instance method only hinder concurrent access to the same instance of the class. You would see your expected effect if the run method was static. But I do not suggest making the run method static. In fact you cannot if it is to keep its current functionality. What you should instead consider is using m1.join() to wait for m1 to finish. Another approach which works better if you have multiple threads which are to wait for each other is to use a CyclicBarrier or a CountDownLatch.