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/
Related
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.
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
}
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.
here is the code
public class TestDeadlockExample1 {
public static void main(String[] args) {
final String resource1 = "xyz";
final String resource2 = "pqr";
// t1 tries to lock resource1 then resource2
Thread t1 = new Thread() {
public void run() {
synchronized (resource1) {
System.out.println("Thread 1: locked resource 1");
try { Thread.sleep(10000);} catch (Exception e) {}
synchronized (resource2) {
System.out.println("Thread 1: locked resource 2");
}
}
}
};
// t2 tries to lock resource2 then resource1
Thread t2 = new Thread() {
public void run() {
synchronized (resource2) {
System.out.println("Thread 2: locked resource 2");
try { Thread.sleep(10000);} catch (Exception e) {}
synchronized (resource1) {
System.out.println("Thread 2: locked resource 1");
}
}
}
};
t1.start();
t2.start();
System.out.println("completed");
}
}
here
t1.start();
t2.start();
System.out.println("completed");
here
in this t1.start() and t2.start() are written in sequential order, so my doubt is that both the thread starts at the same or not
or t1 starts, executes then comes to t2 and executes, if this is correct, how this becomes a deadlock situation..i want to know the execution of these threads
When you launch your java program, JRE spawns main thread and that main thread executes your main method.
When you call t1.start(), new thread spawns and executes first anonymous class's run method. From this point there are 2 threads executing simultaneously in your program: "main thread" and "thread 1".
When you call t2.start(), another thread spawns and executes second anonymous class's run method. From this point there are 3 threads executing simultaneously in your program: "main thread", "thread 1", "thread 2".
The order in which threads are executing is not defined. It could be anything. Generally they are executing simultaneously.
Your "thread 1" and "thread 2" acquire locks on resource1 and resource2 correspondingly and sleep for 10 seconds. While that happens, your "main" thread finishes its execution. But there are 2 more threads in your program, so while main method finished, program is not finished yet.
After sleeping your "thread 1" and "thread 2" trying to acquire locks on resource 2 and resource 1, but those locks are already acquired so they will wait until lock holder will release it. Lock holder will never release it, as it waits for other resource so this program will never stop. That's classic deadlock situation.
I have learned that to prevent deadlocks, you need to make the synchronized block be consistently the same.
public void run() {
synchronized (resource1) {
synchronized (resource2) {
System.out.println("Thread 1: locked resource 1");
System.out.println("Thread 1: locked resource 2");
try { Thread.sleep(10000);} catch (Exception e) {}
}
}
}
and
Thread t2 = new Thread() {
public void run() {
synchronized (resource1) {
synchronized (resource2) {
System.out.println("Thread 2: locked resource 2");
System.out.println("Thread 2: locked resource 1");
try { Thread.sleep(10000);} catch (Exception e) {}
}
}
}
};
in this t1.start() and t2.start() are written in sequential order, so
my doubt is that both the thread starts at the same or not or t1
starts, executes then comes to t2 and executes
A call to start() doesn't ensure that a Thread starts immediately. A native call is made via start0() which inturn calls the OS to fork a thread. So, basically, thread2 can start before thread1. You have no control over which thread starts first.
how this becomes a deadlock situation
There is a probability of deadlock here because t1 might get lock on resource1 and t2 might get lock on resource2 at the same time. Now, both threads want the resource held by the other thread. Hence you have a deadlock.
So as a standard practice, both t1 and t2 should acquire lock in the same sequence.
sleep() guarantees that both t1 and t2 acquire their first lock before they proceed to their second lock. No matter which thread runs first.
"so my doubt is that both the thread starts at the same or not or t1 starts, executes then comes to t2 and executes"
Simply because the threads t1 and t2 are spawned sequentially, does not imply that they execute sequentially. Threads are used for parallel execution of units of work.
Due to the sleep method calls in your code, it will deadlock because
t1 acquires R1 or t2 acquires t2. The order is indeterminate
Both threads sleep for 10 seconds after acquiring their respective resource, so we can be say with high degree of certainty in this example that both threads have acquired the resources at some point during the sleep period of the other.
When t1 or t2 wake up and try to acquire the second resource, which is already held by the respective threads sibling it will block. Both threads will block attempting to acquire the resource held by the other.
This scenario only occurs because the threads are executing in parallel, not sequentially.
Please see http://docs.oracle.com/javase/tutorial/essential/concurrency/deadlock.html
The order of thread execution is not defined.
There is a high risk for your program to go to deadlock. But you can slightly change the order of lock in the second thread to avoid deadlock. I've modified and given below. Again this depends on the logic you are going to write.
Thread t2 = new Thread() {
public void run() {
synchronized (resource1) {
System.out.println("Thread 2: locked resource 2");
try { Thread.sleep(10000);} catch (Exception e) {}
System.out.println("Thread 2: Waiting for resource 1...");
synchronized (resource2) {
System.out.println("Thread 2: locked resource 1 and 2");
}
}
}
};
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) {
}
}
}