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.
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
This question already has answers here:
Run Java Threads sequentially
(13 answers)
Closed 4 years ago.
Lets say I have 3 threads which implement a Runnable interface, and I've started them using below statements.
t1.start();
t2.start();
t3.start();
Is there any way using join(), wait(), notify() combination to make threads end in this order t3 , t2, t1 ?
Nope, the threads will terminate depending on what happens inside of their run() method implementations. If you're simply given a currently-running thread without any access to the code it's executing, there is no way to force it to terminate (aside from calling stop() or destroy(), which are both deprecated and should not be used).
If you can write the code that these threads are running, however, it'd be really simple:
Thread t3 = new Thread(() -> {
System.out.println("Thread 3 terminating...");
});
Thread t2 = new Thread(() -> {
try { t3.join(); } catch(InterruptedException e) {};
System.out.println("Thread 2 terminating...");
});
Thread t1 = new Thread(() -> {
try { t2.join(); } catch(InterruptedException e) {};
System.out.println("Thread 1 terminating...");
});
t1.start();
t2.start();
t3.start();
Sounds like you might want a producer consumer model.
BlockingQueue<Callable<Boolean>> queue1 = new LinkedBlockingQueue<>();
Thread t1 = new Thread(()->{
//do work.
queue1.add(()-> someTask() );
//do more work.
queue1.add(()-> someTaskThatReturnsFalse() );
}).start();
Thread t2 = new Thread(()->{
boolean shouldBeRunning = true;
while(shouldBeRunning){
Callable<Boolean> r = queue1.poll();
shouldBeRunning = r.call();
}
}).start();
You can have as many queues as you like. There are other ways too using locks and barriers. This could be done using join/wait/notify but you would essentially be re-creating the LinkedBlockingQueue.
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.
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.
The Javadoc for the method Condition.newCondition() states "The ordering of lock reacquisition for threads returning from waiting methods is the same as for threads initially acquiring the lock, which is in the default case not specified, but for fair locks favors those threads that have been waiting the longest."
Does that mean that, with explicit locks, threads awakening from a condition compete for the lock acquisition together with the threads initially acquiring it, just as it occurs with implicit locks?
In other words, having two groups of threads, one who is trying to acquire the lock for the first time, and one who are trying to re-acquire the lock after having waited on a condition and being signaled, is the latter favored over the former on the lock acquisition?
Does the lock fairness value affects in any way the lock acquisition order of the these two groups?
In other words, having two groups of threads, one who is trying to acquire the lock for the first time, and one who are trying to re-acquire the lock after having waited on a condition and being signaled, is the latter favored over the former on the lock acquisition?
No, unless the Lock is “fair”, it’s most likely the opposite: typical implementations favor the thread just acquiring the Lock because it has less overhead to let that thread succeed instead of putting that thread to sleep and wake up another.
Does the lock fairness value affects in any way the lock acquisition order of the these two groups?
No, the lock acquisition makes no difference at that point. When a thread waiting on a Condition is signaled there might be other threads waiting longer for a first time acquisition. And a “fair” Lock will prefer the longest waiting thread.
For fair locks, a therad which reqcquires the lock after having singaled has to line up at the end of the lock queue.
The following short program demonstrates this behavior.
T1 acquires the lock first and then invokes await on a condition associated with this lock.
T2 then acquires the lock and waits until T3 tried to acquire the lock as well and then invokes a signal on the condition.
T3 waits some time before acuiring the lock which is hold by T2.
When T2 invokes signal, then T1 tries to reacquire the lock. When T2 releases the lock, then both T1 and T3 are competing for the lock, but T3 gets the lock first.
public class Test {
public static void main(String[] args) throws Exception {
final Lock r = new ReentrantLock(true);
final Condition c = r.newCondition();
Thread t1 = new Thread( () -> {
System.out.println("T1 try lock");
r.lock();
System.out.println("T1 got lock");
System.out.println("T1 invokes await and releases lock");
try { c.await(); } catch (InterruptedException e) { }
System.out.println("T1 reqcquired lock");
r.unlock();
} );
Thread t2 = new Thread( () -> {
sleep(50);
System.out.println("T2 try lock");
r.lock();
System.out.println("T2 got lock");
sleep(100);
c.signal();
System.out.println("T2 signaled");
sleep(100);
r.unlock();
} );
Thread t3 = new Thread( () -> {
sleep(100);
System.out.println("T3 try lock");
r.lock();
System.out.println("T3 got lock");
r.unlock();
} );
t1.start();
t2.start();
t3.start();
}
static void sleep(long millis) {
try { Thread.sleep(millis); } catch (InterruptedException e) { }
}
}
The output is
T1 try lock
T1 got lock
T1 invokes await and releases lock
T2 try lock
T2 got lock
T3 try lock
T2 signaled
T3 got lock
T1 got signal and reqcquired lock