Join() in multithreading - java

According to join definition, the join thread executes till its execution is complete and is not prempted in the middle (correct me if i am wrong) .But in the following code: the join thread t1 doesnt stop the main thread to take the control in between the execution of t1. why so ?
public class JavaAtomic {
public static void main(String[] args) throws InterruptedException {
ProcessingThread pt = new ProcessingThread();
Thread t1 = new Thread(pt, "t1");
t1.start();
Thread t2 = new Thread(pt, "t2");
t2.start();
t1.join();
t2.join();
System.out.println("Processing count=" + pt.getCount());
}
}
class ProcessingThread implements Runnable {
private int count;
#Override
public void run() {
for (int i = 1; i < 5; i++) {
processSomething(i);
count++;
System.out.println(Thread.currentThread()+"---"+getCount()) ;
}
}
public int getCount() {
return this.count;
}
private void processSomething(int i) {
// processing some job
try {
Thread.sleep(i * 1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
output:
Thread[t1,5,main]---1
Thread[t2,5,main]---2
Thread[t1,5,main]---3
Thread[t2,5,main]---4
Thread[t1,5,main]---5
Thread[t2,5,main]---5
Thread[t2,5,main]---6
Thread[t1,5,main]---7
Processing count=7
Many Thanks
Jayendra

Here's what is happening in your example:
Main thread starts running, instantiates and kicks off t1 and t2
t1 runs a little
t2 runs a little
The main thread joins on t1 and blocks until t1 finishes
t1 and t2 keep doing their thing. We continue to see output from them. Main thread is blocking.
t1 finishes and main thread unblocks
Main thread joins on t2. However, it just so happens that in your particular output example, t2 actually finished before t1, which is entirely possible under the randomness of the thread scheduler. So, the main thread doesn't block on this second join() call because t2 is already done.
The main thread runs to completion and program exits.
ADDITION
The above answer is unchanged. However I noticed a thread safety issue in your code. You have multiple threads incrementing the count variable in the shared ProcessThread instance by using the ++ operator. Please note that ++ is not atomic (see this article), because it really consists of four operations: reading the current value of count, adding 1 to it, writing the new value back to count, and returning the value to the caller. In the gaps between those four operations, the thread scheduler could pre-empt the current thread and slip in another one carrying an outdated value read from count. Try increasing the number of threads and decreasing the time in your sleep() call and you will see the current count number appear inconsistent (same number may appear more than once, lower before higher, etc.) count becomes subject to race conditions between threads. The solution is to either enclose all reads/writes to count in synchronized, or to use a java.util.concurrent.atomic.AtomicInteger.

Join stops the thread that calls join. It has no effect on the thread joined.

when you call t1.join(), it won't have any effect on t1's execution. i.e It can't stop t1. t1.join() will wait for t1 to finish and then go forward in the execution.

When main thread reaches the code t1.join() both t1 and t2 have been started and now main thread will wait for t1 to finish. But we can't predict the behaviour of running of t1 and t2, we can only assure that the last line of main function System.out.println("Processing count=" + pt.getCount()); will execute only after thread t1 and t2 finish execution.

Related

Why wait method doesn't work on Thread object? [duplicate]

This question already has an answer here:
After executing wait(), how long does a thread wait if it does not get notified from other threads?
(1 answer)
Closed 2 years ago.
Thread t2 = new Thread();
Thread t3 = new Thread();
t1.start();
t2.start();
synchronized (t2) {
t2.wait(20000);
}
t3.start();
The above program runs without t2 waiting for 20sec. I observed that when thread object is started then it wont wait. Why is this happening?
Why is this happening?
First, let's be clear. This function call, t2.wait(20000) does not do anything to the t2 thread. In fact, it doesn't really do anything at all. All it does is not return until either one of two things happens;
Some other thread calls t2.notify(), or
20 seconds elapse.
If the call took less than 20 seconds to return, then that's probably because the t2 thread itself called t2.notify() just before it died. In most implementations of the Java standard library, the join() method is implemented by using wait() and notify() calls on the thread object.
(Note: most authors will advise you not to ever call wait() or notify() on a Thread instance precisely because of the potential for interference between your code and the library code when both call the same methods on the same instance.)
The above program runs without t2 waiting for 20sec.
As somebody else already has pointed out here, You have not provided any run() method for your t2 thread, so it's unclear why you would expect the t2 thread to "wait" or, to do anything else at all. The only thing a thread ever does is execute the code that you provide for it in a run() method.
The default Thread.run() method would call the run() method of a delegate object that you supply when you construct the threads, but your code supplies no delegate. In that case, the default run() method does nothing at all.
Use sleep to pause the thread regardless of having work to finish.
wait doesn't pause the thread, it just waits the thread to finish (and this thread already finished).
class SleepThread extends Thread {
//run method for thread
public void run() {
for(int i=1;i<5;i++) {
try {
//call sleep method of thread
Thread.sleep(20000);
}catch(InterruptedException e){
System.out.println(e);
}
//print current thread instance with loop variable
System.out.println(Thread.currentThread().getName() + " : " + i);
}
}
}
class Main{
public static void main(String args[]){
//create two thread instances
SleepThread thread_1 = new SleepThread();
SleepThread thread_2 = new SleepThread();
//start threads one by one
thread_1.start();
thread_2.start();
}
}
Thread sleep method in java

Thread.Join not working as expected

I am working on a small example using join method and Thread.sleep, but I am confused how the flow works.
Here is my program:
public class Test implements Runnable {
private String msg;
private int seconds;
public Reminder(int sec, String msg) {
this.sec= sec;
this.msg= msg;
}
public void run() {
try {
Thread.sleep(sec* 1000);
System.out.print(msg+ " ");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
public static void main(String[] args) throws InterruptedException {
Thread t1 = new Thread(new Test(1, "one"));
Thread t2 = new Thread(new Test(3, "two"));
t2.start();
t1.start();
t2.join();
t1.join();
}
}
Since I am calling t2.join(), the t2 thread should complete before t1 thread completes.
So I am expecting output as two one, but I am getting output as one two
Since I am calling t2.join(), the t2 thread should complete before t1
thread completes.
This is not correct , join will not guarantee which thread will finish first , the two threads started so no guarantee which one will finish first, join will block the main thread until the thread finishes, so basically all you are doing with join is you are blocking main thread from waiting the next thread to finish which may already finished.
if you want t1 to start after t2 finishes then you need to call start after t2 finishes and here you can use join
t2.start();
t2.join();//main thread will stop here untill t2 is finished
t1.start()
This is actually not practical since no real difference between it and doing your tasks in one thread, just the overhead of creating threads
Since I am calling t2.join(), the t2 thread should complete before t1 thread completes.
Not at all. You wait for t2 to end - but that doesn't prevent the other thread from progressing.
So only the first part of your assumption is correct. That code waits for t2 to complete. That doesn't have any effects on the "completeness" of t1.
Assume you have two runners, starting at the same point in time. You sit at the finish line, and you only observe the slower runner. Now the slower runner passes the finish line. Why would you expect the faster runner to still be running? He made it to the finish line whilst you were only looking at the slower guy!
Since I am calling t2.join(), the t2 thread should complete before t1
thread completes.
It is not the case if t1 that is started first has terminated its execution before
t2.join(); is executed.
To allow t2 to be completed before t1, start t2, invoke join() on it. Then start t1:
t2.start();
t2.join();
t1.start();
But it defeats in a some way multi threading as each thread is started only as the previous is terminated.
The threads are starting to run rightaway after you call start(). This inclused the writeln().
join() merely collects some resources from the thread, blocking until the thread is done in the process.
Join method makes the main thread wait for the other thread to complete executing before it can carry out the next code after the join function call.
This has nothing to do with the interrelationship between two or more threads that you spawn.

Order of execution java statements

Since order of execution is not guaranteed. In below program order of execution for main method can be like below ?
t2.start();
t2.join();
t1.start();
t1.join();
Program is:
public class Puzzle {
static boolean answerReady = false;
static int answer = 0;
static Thread t1 =
new Thread() {
public void run() {
answer = 42;
answerReady = true;
}
};
static Thread t2 =
new Thread() {
public void run() {
while (!answerReady) Thread.sleep(100);
System.out.println("The meaning of life is: " + answer);
}
};
public static void main(String[] args) throws InterruptedException {
t1.start();
t2.start();
t1.join();
t2.join();
}
}
Edit: want to add few things after seeing comments
answerReady may never become true. Agree.
what are special conditions when order of execution can be changed ?
why main method is correctly synchronized here ?
The Java Language Specification dictates what conforming JVMs may do or not. See
§17.4.5. Happens-before Order
Two actions can be ordered by a happens-before relationship. If one action happens-before another, then the first is visible to and ordered before the second.
If we have two actions x and y, we write hb(x, y) to indicate that x happens-before y.
If x and y are actions of the same thread and x comes before y in program order, then hb(x, y).
…
Since your invocations of start() and join() are actions of the same thread, they are ordered in respect to the program order.
I think, it should be obvious that if that simple guaranty didn’t exist, even single threaded programming was impossible.
This does not imply the absence of reordering in the code. It only implies that such optimizations must happen in a way that retains the observable behavior of these actions when executing this code.
The point here is, that while the main thread will consistently do what you told it to do, other threads not having a happens-before relationship to either of these actions, might not see the actions in the same way. In your case, with the three threads shown, there are several relationships:
continuation of §17.4.5
…
If hb(x, y) and hb(y, z), then hb(x, z).
…
A call to start() on a thread happens-before any actions in the started thread.
All actions in a thread happen-before any other thread successfully returns from a join() on that thread.
From this you can derive that all three threads of your code agree on what the main thread is doing in most parts.
Of course, this doesn’t change the fact that the two spawned threads are improperly (not at all) synchronized and t2 may print the value 0 instead of 42 or never terminate at all.
No. the order of execution on the main thread is as you've declared it in main:
t1.start();
t2.start();
t1.join();
t2.join();
The only thing that's not guaraneed is the content of the threads t1 and t2.

Program gets halted: wait() and notify()

I am trying to achieve this: Created two different threads, one prints odd numbers, one prints even numbers. Once one thread prints a number, it has to wait for the other thread and so on, that is one-after-other.
To achieve this, i am using synchronized block along with wait() and notify().
I am creating a class whose's object will be used to pass to synchronized block in both the threads.
Here is the code:
--> This is used object which will be passed to synchronized block.
package com.vipin.multithread.variousdemos;
public class SyncObject {
public SyncObject () {
}
}
Odd Thread:
package com.vipin.multithread.variousdemos;
public class OddThread implements Runnable {
private Thread t;
int index=0;
SyncObject so=null;
int odd_nums[] = {1,3,5,7,9};
public OddThread(SyncObject so) {
t = new Thread(this,"Odd Thread");
this.so = so;
t.start();
}
public Thread getThreadInstance() {
return t;
}
#Override
public void run() {
while (true) {
synchronized(so) {
System.out.println("Odd num is --->" + odd_nums[index]);
try {
so.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
index++;
so.notify();
if(index>=5) {
return;
}
}
}
}
}
Even Thread: UPDATE
package com.vipin.multithread.variousdemos;
public class EvenThread implements Runnable {
private Thread t;
int index=0;
SyncObject so=null;
int even_nums[] = {2,4,6,8,10};
public EvenThread(SyncObject so) {
t = new Thread(this, "Even thread");
this.so = so;
t.start();
}
public Thread getThreadInstance() {
return t;
}
#Override
public void run() {
while(true) {
synchronized(so) {
System.out.println("Even num is --->" + even_nums[index]);
so.notify(); <-- Here we are notifying.
try {
so.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
index++;
//so.notify(); <-- commented out.
if(index>=5) {
break;
}
}
}
}
}
Main Application:
package com.vipin.multithread.variousdemos;
public class EvenOddDemo {
public static void main(String[] args) throws InterruptedException {
SyncObject so = new SyncObject();
OddThread ot = new OddThread(so);
EvenThread et = new EvenThread(so);
System.out.println("\nIn main thread");
Thread.sleep(1000000000);
System.out.println("Exiting main thread...");
}
}
---> As seen in the code, I am creating two threads to print even and odd numbers. I am using synchronized block, and passing object of type ==> SyncObject.
SyncObject I am passing as argument to these different threads in main.
However, this programs halts, i.e stuck only first statement gets executed, and then it waits forever:
Here is the output:
Odd num is --->1
In main thread
Even num is --->2
I am not able to understand why this program waits for ever, I am using SAME object on which we are invoking synchronized(), wait() and notify(). As per my understanding, it should work, not sure why this is not working.
Any clues as to why this is waiting forever.
UPDATE:
I did some changes in the code, UPDATE and it works fine.
I still have some doubt. Does notify() be called by the thread even if it has not locked the monitor, like in my case after i updated the code.
Sequence of events:
Odd thread gets executed first, then it calls wait() <-- it releases the monitor and now in sleep mode.
Even thread runs, prints msg, and calls notify() <-- here i am not having clear understanding.
When Even thread calls notify(), at that point it has the monitor, so when it calls notify(), does is still own the monitor?
Now, after Even thread calls notify(), then Odd thread gets notified, and hence it starts execution from the point it was sleeping. It is doing some execution and calls notify(), at that points I presume Odd thread is NOT owning the monitor, it calls notify(). So, my question is, does notify() work same whether or not the thread owns the monitor?
It is only when one do the code, one really understands this. I read book and i felt i understood everything, and seems i am back to square one!
The problem here is simply that both threads go straight into wait. Thread 1 gets so, prints value then waits. Thread 2 then gets so, prints value then waits. So both are sleeping away, since nobody is there to notify them. So, a simple fix would be to do so.notify(), right before so.wait(). Then they're not infinitely waiting.
EDIT
Odd thread starts, executes & then waits. Then even thread starts, executes, notifies & then waits. Even thread holds the lock over the monitor until it goes into wait.
When the even thread called on notify, the odd thread awakens & polls for the lock. Once the even thread goes into wait (& releases the lock), then the odd thread can obtain the lock.
If the even thread had not called on notify, then the odd thread would continue to sleep. The even thread would have gone to wait & released the lock. No thread is polling or attempting to obtain the lock, hence the program remains in the suspended state.
The documentation also provides a similar explanation. I hope that clears your doubts.

Java: Thread doesn't work

I'm trying to start a thread in a for-loop. This task should only wait for a second (Thread.sleep()), so every time the loop starts over again, a new thread is started and it should cause the code after the thread to wait until it is executed.
public void count()
{
for(int i = 29; i>=0; i--)
{
Thread t1;
t1 = new Thread(new TimerClass());
t1.start();
String s = String.valueOf(i);
jLabel6.setText(s);
System.out.println(s);
}
}
public class TimerClass implements Runnable{
#Override
public void run()
{
try{
Thread.sleep(1000);
System.out.println("Timer");
} catch(InterruptedException e)
{
}
}
}
As you can see, I implemented in both methods System.out.println() to check if they are actually executed. I get this:
29
28
27
26
...//25 - 3
2
1
0
Timer
Timer
Timer
//in all 29 times Timer
So it should be 29, Timer, 28, Timer and so on, but it isn't.
Does anyone know what's wrong with the code?
Thanks a lot.
Your main loop that is starting the thread is likely dominating the CPU, so it finishes doing its entire loop and only then do the threads get a chance to go.
In fact, given that all of your threads sleep for an entire second and you're only looping 29 times, you're guaranteed that your loop will finish (and print all of the numbers) before your threads do. Add a sleep to your main loop if you want the threads to print - remember, the main loop doesn't stop when you start a thread.
You can join a thread to the main thread so first your thread will finished then main thread
public void count()
{
for(int i = 29; i>=0; i--)
{
Thread t1;
t1 = new Thread(new TimerClass());
t1.start();
t1.join();
String s = String.valueOf(i);
jLabel6.setText(s);
System.out.println(s);
}
}
Here is my code for spawning 2 threads or one thread depends on arrayList size but in my case this threads are doing much more complex tasks then just waiting 1 sec
for (int i = 0; i < array.size(); i += 2) {
Thread t1 = null;
Thread t2 = null;
if (i < array.size() - 1 && array.size() > 1) {
t1 = new Thread(array.get(i));
t2 = new Thread(array.get(i + 1));
t1.start();
t2.start();
}
else {
t2 = new Thread(array.get(i));
t2.start();
}
if (t1 != null)
t1.join();
if (t2 != null)
t2.join();
}
In my code I populate arrayList with Objects that Implements Runnable interface.
Even if you sleep the thread for 1ms, your results would be the same. If you can manage the thread to sleep for the time less than it takes to print the results, your result could be as expected. Here is my code where I have put the time of 1 ms but yet the results are the same.
public class MultiThreading implements Runnable
{
public void run()
{
try
{
Thread.sleep(1);
System.out.println("Timer");
}
catch(Exception e)
{
}
}
public static void main(String [] args)
{
for(int i = 29; i>=0; i--)
{
Thread t1;
t1 = new Thread(new MultiThreading());
t1.start();
String s = String.valueOf(i);
System.out.println(s);
}
}
}
If you comment out the Thread.sleep(1) method, then your results are as you expected.
Delay is much enough to let the for loop in count() to finish before is can print 'timer' from thread.
What is happening is that the thread you started starts executing and immediately goes to sleep. In the meantime, your loop just keeps running. As the whole point of threads is that they run asynchronously, I don't really understand why you think your main loop should be waiting for it to finish sleeping. The thread has started running and is now running independently of the main loop.
If you want to wait for the thread you just started to finish (in which case, you might as well use a method), then use one of the synchronisation primitives, i.e. Thread.wait().
What you actually want to do is block your main thread while another thread is running. Please don't use Thread#sleep statements, as these are unreliable in order to "make your application work". What you want to use instead is Thread#join. See dharr his code for an example.
Also, it's better to use Executors and ExecutorServices when creating threads or running async tasks.
Threads are interesting. Think of a virtual thread as a physical thread. There are many threads on the clothes you're wearing, all working at the same time to hold your shirt together. In virtual terms what Thread.start() does is start a thread on a different strand WHILE the following code continues to execute, (i.e. Two Threads work simultaneously like 2 runners run next to each other). Consider putting a break point right after Thread.start(). You'll understand.
For your desired effect, just put a Thread.sleep() in the main loop. This will cause an output of
29
Timer
28
Timer
// etc.
Hope this helped.
Jarod.
Another analogy to the threads in a shirt:
Think of threads as coworkers to your main programm (which is a thread itself). If you start a thread, you hand some work to this coworker. This coworker goes back to his office to work on this task. You also continue to do your task.
This is why the numbers will appear before the first thread/coworker will output anythig. You finished your task (handing out work to other coworkers) before he finished his.
If you want to give out some work and then wait for it to be finished, use t1.join() as suggested by others. But if you do this, it is senseless to create new Threads, because you don't (seem) to want to process something in parallel (with many coworkers) but in a specific order - you can just du it yourself.

Categories