Why is Thread.join not behaving as expected - java

I am new to the concept of threads. I made this test to understand how join works. join is suppose to cause the calling thread to wait until the thread represented by the join instance terminates. I have two threads t1 and t2. First, t1 calls join and then t2 calls join. I was expecting for t1 to finish before t2 starts since join is called from with the main thread. I was expecting the main thread to wait from the point where the first join is called. But that is not how it behaves. t1, t2 and the line that prints "Thread" starts running in parallel. How did the main thread manage to print and call t2 since it was suppose to be waiting for t1 to finishes?
public static void main(String[] args) throws InterruptedException, ExecutionException {
Thread t1 = new Thread(new A());
Thread t2 = new Thread (new B());
t1.start();
t2.start();
t1.join();
System.out.println("Thread");
t2.join();
}

You are calling join in the wrong order. Start t1 and then call join so that the main thread will wait for t1 to die then start t2.
public static void main(String args[]) throws InterruptedException{
Thread t1 = new Thread(() -> System.out.println("a"));
Thread t2 = new Thread (() -> System.out.println("b"));
t1.start();
t1.join(); //main waits for t1 to finish
System.out.println("Thread");
t2.start();
t2.join(); //main waits for t2 to finish
}
Output:
a
Thread
b
When you are starting both t1 and t2 and then calling t1.join() the main thread is indeed waiting for t1 to die, so t1 will execute till it finishes but in the background t2 has already started executing so that is why you see both threads are running in parallel.
public static void main(String args[]) throws InterruptedException{
Thread t1 = new Thread(() -> System.out.println("a"));
Thread t2 = new Thread (() -> System.out.println("b"));
t1.start(); //Started executing
t2.start(); //Started executing
t1.join(); //main thread waiting for t1, but in the background t2 is also executing independently
System.out.println("Thread");
t2.join(); //main again waiting for t2 to die
}

Related

Waiting for a thread to finish with .join incosistent

Consider this code:
public class print extends Thread {
public void run() {
Out.print("Hello");
Out.println("World");
}
}
public class test {
public static void main (String[] args) {
Thread t1 = new print();
Thread t2 = new print();
Thread t3 = new print();
Thread t4 = new print();
Thread t5 = new print();
t1.start();
t2.start();
t3.start();
t4.start();
t5.start();
try {
t1.join();
t2.join();
t3.join();
t4.join();
t5.join();
}catch(InterruptedException e) {
}
}
}
The goal is to print out hello, than world in the next line.The output isn't right,and it is very inconsistent, meaning every few test it changes.I've never worked with threads,but I did some reaserch and it says that using this .join should wait for one thread to finish so that the next one starts. What am I doing wrong?
Thank you!
and it says that using this .join should wait for one thread to finish so that the next one starts
That is not what join does.
join blocks the current thread until the target thread is finished. It does not do anything about any other threads.
In your case, the main thread will wait for t1 to finish, then for t2 and so on. But it does nothing to schedule how t1 runs in relation to t2. In particular, it also does not delay starting t2. t2 starts when you said t2.start().
Okay,so how do I tell the others to wait as well?
Ideally you use higher level constructs like work queues and executor services instead of messing with low-level threading primitives.
If you do want to continue doing that, look at ReentrantLock or CountDownLatch. Or have t1 call t2.join().
I would probably use a CountDownLatch. Set up the latch to require five tickets, then each of your threads can print the first line, then block at the latch, and only when the latch releases (which happens when all five have arrived), they will continue to print the second line.
Also note that if you want to run these tasks in a sequence one after the other, you do not need multiple threads at all. Just do t1.run(); t2.run(); t3.run(); on the same thread.

Why we create new thread and use join() to make parent thread waiting?

After reading about join method I've some doubt: I think multithreading is a way to introduce parallelism in our program and believe some time we need some thread finished before another. But I don't understand why a programmer write something like this:
public static void main(String[] args) {
Thread t1 = new Thread(new MyRunnable(), "t1");
Thread t2 = new Thread(new MyRunnable(), "t2");
t1.start();
t1.join();
t2.start();
t2.join();
}
whats the advantage of using thread in this example vs below code:
public static void main(String[] args) {
Thread t1 = new Thread(new MyRunnable(), "t1");
Thread t2 = new Thread(new MyRunnable(), "t2");
t1.run();//just run the task of thread without start new thread
t2.run();
}
in first example main thread should pause until t1 finished and then start t2 and wait until finished and in second example it happen too.
Why we create new thread and use join() to make parent thread waiting? why can't use parent thread instead of new thread?
In both ways, you are not getting benefits.
In your first example, you have two threads and join() is not useful.
But assume a scenario where
You have multiple threads ( Main thread, T1, T2, T3 and T4)
Main, T1,T2 can run in parallel but T3 should wait for completion of T4
In above case, all threads can start in parallel but you join only T3 and T4 threads.
Refer to below post for use cases of join():
Why we should use Join in threads?
If you want to explore advanced version of multi-threading, use CountDownLatch in place of join()
The first way doesn't take profit of multi threading.
We could write it with a single thread, it changes nothing in terms of multi threading :
Thread t1 = new Thread(new MyRunnable(), "t1");
t1.start();
t1.join();
t1 = new Thread(new MyRunnable(), "t2");
t1.start();
t1.join();
The second way that uses t1.run(); instead of t1.start();
doesn't start the thread and so these :
t1.run();
t2.run();
are simple synchronous (blocking) calls to the Thread objects.
Only after t1.run() is returned, t2.run() is invoked.

Why threads are not working?

Here is my following code:
private int counter = 0;
public void incC() {
counter++;
System.out.println("Counter is: "+counter + " "+Thread.currentThread().getName());
}
public void printC() {
System.out.println("Counter is: "+counter + " "+Thread.currentThread().getName());
}
public static void main(String args[]) throws Exception {
Stuff stuff = new Stuff();
Thread t1 = new Thread(() -> {
stuff.incC();
});
Thread t2 = new Thread(() -> {
stuff.printC();
});
t1.start();
t2.start();
t1.join();
t2.join();
}
}
Here's my output:
Counter is: 1 Thread-1
Counter is: 1 Thread-0
Here t1.join() is called first. So shouldn't thread t2 should wait for thread t1 to die?
How's it possible for thread t2 to output first before t1?
t1.join() makes the current thread wait for thread t1 to die. It has no effects on the timing of any other thread but the current one. You have started two threads and they will run concurrently with no ordering constraints.
I should also note that starting two threads only to have one wait for the other's death defeats the purpose of multithreading.
join() forces to wait current (in your case the main) thread to death of t1, so t2 continues to work
Order for thread execution is not fixed because they work in parallel
Both threads works in parallel and therefore no guarantee on which thread will finish first in your case.
If you want a specific thread to finish first you have to start it and join it with your main thread then start and join the second thread like follows.
t1.start();
t1.join();
t2.start();
t2.join();
Set names for the threads for better understanding.
Also change your question because your threads are working fine.

Is it possible to call Thread start() and join() in a single call?

I'm playing with threads in Java and i have a question about the join() method.
Let's say i have a SampleClass that extends Thread. I instantiate some new threads in the main but i want the thread's job to be completed sequentially using join().
public static void main(String[] args) {
for(int i=0; i<5; i++){
new SampleClass().start();
}
}
Is it possible to call immediately join()? ...something like this:
new SampleClass().start().join();
Or is there another approach to use? ...like this maybe:
new SampleClass().start();
try{Thread.currentThread().join();}catch(InterruptedException e){...}
Thank you very much
new SampleClass().start().join(); This is wrong.
You can achieve similar thing by
SampleClass samClass = new SampleClass();
samClass.start();
samClass.join()
The above code will have same effect as you wanted.
Now your problem is to run the Threads Sequentially. In most of these
cases you don't need threads to execute sequentially (But yes there are some scenarios).
Well If you do have to.
Then you can Do Like this
Thread t1 = ..
Thread t2 = ..
t1.start();
t1.join();
t2.start(); // t2 will start only when t1 dies
t2.join(); //
t3.start(); // t3 will start only when t2 dies..
But the above approach is not good. Because for other thread to start, previous thread
needs to die. In practice We should think of creating threads as an expensive operation
and try to reuse.
The real problem often is like this, You have to execute tasks T1 , T2 , T3 , T4
sequentially but in different Threads T1 && T3 have to run on one threads and T2 and T4
have to run on another.
So here we can use Two threads instead of 4.
Thread1 will run T1 and then Thread2 will run T2 and then Thread1 will run T3 and so on
i.e.
Thread1 -> T1
Thread2 -> T2
Thread1 -> T3
Thread2 -> T4
All task will be executed sequentially but using 2 threads only.
You can solve the problem like below
Thread1 ->run {
while(canIrun) {
executeTask(taskQueue1.next());
notifyThread2();
waitForThread2Signal();
}
}
Thread2 -.run {
while(canIrun) {
waitForThread1Signal();
executeTask(taskQueue2.next());
notifyThread1();
}
}
The wait and notify method can be implemented using CyclicBarrier very easily.
What would be the point? You can get the same effect, without the overhead, by just calling run().
You can use ExecutorService#submit(Runnable runnable).get()
Is it possible to call immediately join()?
No it is not as start() returns void . You cannot chain those methods that way. And you need to invoke join() on a Thread object.
Method start belongs to Thread class. It would be like doing this:
Thread thread = new Thread(someRunnableTask);
//This fails to compile, because start returns NOTHING (void). This variable will not be filled with pointer to our thread object.
Thread ourOriginalThreadPointer = thread.start();
//Hence this variable references to nothing, no method can be called.
ourOriginalThreadPointer.join()
The instanciated thread doesn't need to be anonymous. You can do that:
public static void main(String[] args) {
for(int i=0; i<5; i++){
SampleClass sc = new SampleClass();
sc.start();
try {
sc.join();
} catch (InterruptedException e) {
}
}
}

Understanding join() method example

The Java thread join() method confuses me a bit. I have following example
class MyThread extends Thread {
private String name;
private int sleepTime;
private Thread waitsFor;
MyThread(String name, int stime, Thread wa) { … }
public void run() {
System.out.print("["+name+" ");
try { Thread.sleep(sleepTime); }
catch(InterruptedException ie) { }
System.out.print(name+"? ");
if (!(waitsFor == null))
try { waitsFor.join(); }
catch(InterruptedException ie) { }
System.out.print(name+"] ");
And
public class JoinTest2 {
public static void main (String [] args) {
Thread t1 = new MyThread("1",1000,null);
Thread t2 = new MyThread("2",4000,t1);
Thread t3 = new MyThread("3",600,t2);
Thread t4 = new MyThread("4",500,t3);
t1.start();
t2.start();
t3.start();
t4.start();
}
}
In which order are the threads terminated?
What actually confuses you about Thread.join()? You haven't mentioned anything specific.
Given that Thread.join() (as the documentation states), Waits for this thread to die, then t4 will wait for t3 to complete, which will wait for t2 to complete, which will wait for t1 to complete.
Therefore t1 will complete first, followed by t2, t3, and t4.
It would terminate in order t1, t2, t3, t4... join causes the currently executing thread to wait until the thread it is called on terminates.
There is a main thread which starts the four customs threads you created t1,t2,t3 and t4. Now when join() method is invoked on a thread and no argument(time) is supplied(which makes it 0 by default meaning maximum wait time is forever) then the calling thread will wait for the thread on which join was invoked to terminate.
When t1.start() is called it's corresponding run() method is invoked by the JVM. Since waitsFor argument is null for t1 it will simply terminate by printing it's name. Since you are adding sleep t2,t3,t4 would be started by the time t1 completes it's sleep. Now t2 will wait for t1 to terminate as we are calling join on t1 from t2. Similarly t3 will wait for t2 and t4 will wait for t3. So youe execution will go t1->t2->t3->t4.
However if t1 terminates before t2 calls join on it, join will simply return because at that point(when t2 calls join on t1) isAlive() will be false.
Surely the order of thread termination would be from t1, t2, and so on here. May be you will get a clear understanding of join() method in java thread from here also http://findnerd.com/list/view/Java-Thread-Join-Example/4465/

Categories

Resources