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.
Related
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
public class SimpleThreads {
// Display a message, preceded by the name of the current thread
static void threadMessage(String message) {
String threadName = Thread.currentThread().getName();
System.out.format("%s: %s%n", threadName, message);
}
private static class MessageLoop implements Runnable {
public void run() {
String importantInfo[] = { "Mares eat oats", "Does eat oats","Little lambs eat ivy", "A kid will eat ivy too" };
try {
for (int i = 0; i < importantInfo.length; i++) {
threadMessage(importantInfo[i]);
}
} catch (Exception e) {
threadMessage("I wasn't done!");
}
}
}
public static void main(String args[]) throws InterruptedException {
threadMessage("Starting MessageLoop thread");
Thread t = new Thread(new MessageLoop());
t.start();
threadMessage("Waiting for MessageLoop thread to finish");
}
}
OUTPUT
main: Starting MessageLoop thread
main: Waiting for MessageLoop thread to finish
Thread-0: Mares eat oats
Thread-0: Does eat oats
Thread-0: Little lambs eat ivy
Thread-0: A kid will eat ivy too
Here at first the main thread printed the message 'main: Starting MessageLoop thread'. After that I started Thread-0 OR MessageLoop thread.
Thread t = new Thread(new MessageLoop());
t.start();
But before starting/printing Thread-0 messages its printing 'main' thread message 'main: Waiting for MessageLoop thread to finish' and Thread-0 was executed after that only. Why ?
That behavior is normal and must be expected, although you can't count on it either way.
You seem to expect the main thread to wait for the second thread to be running. This, however, is not the case with your code. The point of starting a second thread is concurrent execution, implying that that you can't count on the sequence of execution just because the statements in code are sequential.
If you want the main thread to wait for the other thread to execute, then you need to synchronize them. This, however, defeats the purpose of starting the second thread in your case. If you wanted main thread to wait for second thread, you could then just call the method without starting the second thread.
Googling "java concurrency" led to, among other pages, this one. That doc explains a lot of these concepts.
Because invoking start() on a thread doesn't make the thread effectively executed right now.
It is the way which works multithreading.
From Thread.start() documentation :
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 main thread is currently executed as you invoke t.start(); .
The thread will at a time be paused by the JVM but you don't master when.
In your specific case, you will get a reproducible behavior.
As after t.start();, you have a statement very fast to execute :
threadMessage("Waiting for MessageLoop thread to finish");
it never doesn't let the main thread to be paused and the new thread to be effectively run.
Add after t.start();, some statements that take more time to be executed in the main thread or invoke sleep() on it and you should see a different behavior.
Say i have two threads t1 and t2, as per Oracle docs, t1.join means the current thread will wait for t1 to finish.My question is, what if the threads have already finished ? eg:
Thread t1 = new Thread(new EventThread("e1"));
t1.start();
Thread e2 = new Thread(new EventThread("e2"));
t2.start();
while (true)
{
try {
t1.join();
t2.join();
break;
}
}
What if t2 is already finished ?
From the documentation of join():
An invocation of this method behaves in exactly the same way as the invocation
join(0)
And the documentation of join(long millis) says:
This implementation uses a loop of this.wait calls conditioned on this.isAlive.
So if isAlive returns false (i.e. the thread finished), the wait is never called and join just returns immediately.
I was expecting the second thread in the following example to hang, since it waits on an object with no corresponding notify. Instead, it falls through to the println, presumably due to a spurious wakeup.
public class Spurious {
public static void main(String[] args) {
Thread t1 = new Thread() {
public void run() {
System.out.println("Hey!");
}
};
Thread t2 = new Thread() {
public void run()
{
try {
synchronized (t1) {
t1.wait();
}
} catch (InterruptedException e) {
return;
}
System.out.println("Done.");
}
};
t1.start();
t2.start();
}
}
Output:
Hey!
Done.
On the other hand, if one removes the "Hey!" println from the first thread, the second thread will indeed hang. This happens on both MacOS and Linux.
Any idea why?
This is not a spurious wakeup, a spurious wakeup is caused by a race condition in the JVM. This is a race condition in your code.
The println keeps thread1 alive just long enough that thread2 can start waiting before thread1 terminates.
Once thread1 terminates it sends a notification to everything waiting on its monitor. thread2 receives the notification and ceases waiting.
Removing the println reduces the time needed for thread1 to finish so that thread1 has already finished by the time thread2 can start waiting on it. thread1 is no longer alive and its notification has already occurred before thread2 started waiting, so thread2 waits forever.
That threads send a notification when they die is documented in the API for Thread#join:
This implementation uses a loop of this.wait calls conditioned on this.isAlive. As a thread terminates the this.notifyAll method is invoked. It is recommended that applications not use wait, notify, or notifyAll on Thread instances.
(For a thread to call notifyAll it has to hold the lock, if the other thread grabs the lock, it can keep the terminating thread alive and delay the notifyAll until the terminating thread can acquire the lock.)
The moral (well, one of the morals) is to always wait in a loop with a condition variable, see the Oracle tutorial. If you change Thread2 to look like this:
Thread t2 = new Thread() {
public void run()
{
try {
synchronized (t1) {
while (t1.isAlive()) {
t1.wait();
}
}
} catch (InterruptedException e) {
return;
}
System.out.println("Done.");
}
};
then thread2 should exit regardless of whether thread2 can start waiting before thread1 finishes.
Of course this is total toy example territory:
Don't extend Thread, use Runnable or Callable.
Don't lock on threads.
Don't start Threads, use Executors.
Prefer higher level concurrency constructs to wait/notify.
You're waiting on a Thread object. That's bad practice, that is explicitly discouraged in the javadoc of Thread (Thread.join, precisely).
The reason is that when you call thread.join() to block until the thread stops running, you're actually waiting on the thread. And when the thread stops running, it notifies in order to unblock all the callers of join().
Since you waited on the thread, you're implicitly being notified when the thread stops running.
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.