This is a beginner question regarding multithreading in Java.
As per my understanding when multiple (user)threads are created to run the program or application, then there is no concept of Parent and Child threads. They are both independent user threads.
So, if the main thread finishes execution then another thread(Thread2) will still continue its execution because it will not be killed by the JVM until the Thread2's thread of execution is completed (https://docs.oracle.com/javase/6/docs/api/java/lang/Thread.html, https://stackoverflow.com/a/9651919/6700081)
Then why am I not seeing the logs from the .log() being printed by Thread2 when the Main thread exits in the below code:
#Test
public void parentMainThreadAndChildThreadTest_WithSpringWebFlux() throws InterruptedException {
Flux<Long> infiniteFlux = Flux.interval(Duration.ofMillis(100));
infiniteFlux.subscribe((element) -> System.out.println("Value is:::" +element));
Thread.sleep(3000); //Main thread sleeps for 3 seconds
}
I see that if I increase the main thread's life by putting it to sleep then I can see the system out statements. But why aren't they displayed when the main thread is finished even though the Thread2 is still running asynchronously?
The test method is executed by the Main thread's thread of execution so what happens to the Thread2 after main thread finishes in this case?
if the main thread finishes execution then another thread(Thread2) will still continue its execution
this is true only for normal threads. Threads for thread pools usually are configured as daemon threads, which are forced to stop when all normal threads are finished.
In your case,
(element) -> System.out.println("Value is:::" +element)
is executed on a daemon thread taken from a reactor's thread pool.
Related
Let us consider following is our thread:
public class HeavyWorkRunnable implements Runnable {
#Override
public void run() {
System.out.println("Doing heavy processing - START "+Thread.currentThread().getName());
try {
doDBProcessing();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("Doing heavy processing - END "+Thread.currentThread().getName());
}
private void doDBProcessing() throws InterruptedException {
// TODO
}
}
And the main method:
public class ThreadRunExample {
public static void main(String[] args){
Thread t1 = new Thread(new HeavyWorkRunnable(), "t1");
Thread t2 = new Thread(new HeavyWorkRunnable(), "t2");
System.out.println("Starting Runnable threads");
t1.start();
t2.start();
System.out.println("Doing main heavy processing - START "+Thread.currentThread().getName());
System.out.println("Runnable Threads has been started");
}
}
Now the outputs are different at different run times. For example:
Output1:
Starting Runnable threads
Doing main heavy processing - START main
Doing heavy processing - START t1
Doing heavy processing - START t2
Doing heavy processing - END t2
Runnable Threads has been started
Doing heavy processing - END t1
Output2:
Starting Runnable threads
Doing main heavy processing - START main
Runnable Threads has been started
Doing heavy processing - START t1
Doing heavy processing - END t1
Doing heavy processing - START t2
Doing heavy processing - END t2
As per my understanding of thread:
1. Only a single thread can run at a time.
2. The system chooses threads randomly to run if priorities are not set.
So, the system should complete the tasks of 'main' thread, then run either t1 or t2. If so, then the output should always contain:
Starting Runnable threads
Doing main heavy processing - START main
Runnable Threads has been started
as the first three lines.
I'm not getting what I've missed in my understanding.
The thing is: varies between Operating Systems and their processing queues.
This is a lengthy topic, but long story short:
When the three threads are on the system queue, the OS let one of them run only a fraction of time (called quantum), and then pushes it to the queue to let other threads run, and so on, to have an illusion of multitasking in single processor-single core architectures. For this, each execution will be different for a myriad of reasons.
If you really want to dive into this topic, just start here link
Only one thread can run at a given time in a single processor, that is true. But the Java Virtual Machine contains a component which is called the Thread Scheduler. This component do choose which thread goes into the processor and which one gets out.
When you start a thread, it will enter the runnable state. When the thread scheduler have a slot for processing time, it will pick one of all the runnable threads (at random if they all have the same priority). The chosen one enters the running state for a few milli seconds before the Thread Scheduler interrupts the processing and places the thread back into runnable state.
A thread is consequently not guaranteed to finish its job before going out of the processor.
When you are experiencing with threads, you should consider that all threads that you have started can run concurrently, at the exact same time, so there is no guaranteed ordering.
What you may want to check is how to make a thread wait on other threads (using the Object.wait() method), but that's far beyond this answer.
If you need to dive into threading in Java, you should consider a specific training or google for online ressources, because this is not obvious at all.
First Let me clear your understanding that
Only one thread can run at a given time its true but only for single core processor not for multi cores.
Now Main method is nothing but internally a Thread. Now Threading Scheduling and Time Slicing depends on the OS. So, When you run your program Main method still its in Time Slice and hence System.out.println("Doing main heavy processing - START "+Thread.currentThread().getName()); statement is executed and than furthermore statements.
If you want to change your Output than you have to remove your Main Thread From Time Slice of OS.
So,after t2.start(); use Thread.sleep(1000) and you can check that your either t1 or t2 thread will get Scheduler and going for execution.
In the below code:
class Worker extends Thread {
Thread t;
public Worker(Thread thread) {
t=thread;
}
public void run() {
try {
t.join();
} catch(InterruptedException e) {
System.out.println("Exception is thrown and caught");
}
System.out.println(Thread.activeCount());
System.out.print("|work|");
}
public static void main(String[] args) {
Thread t=Thread.currentThread();
Worker worker = new Worker(t);
worker.setDaemon(true);
worker.start();
System.out.println("Exit from main method");
}
}
Since worker is a daemon thread joined on main() thread, |work| should never be printed since the user thread main() completes first, and since worker is a daemon thread it too is stopped when the main() thread dies.
But, the output I get is as follows :
Exit from main method
1
|work|
Please clarify this query for me.
After many many executions of the program, I have observed the following different outputs:
without Thread.sleep(1000) :
Exit from main method
2
Exit from main method
1
|work|
Exit from main method
2
|work|
with Thread.sleep(1000) :
Exit from main method
2
|work|
Exit from main method
Notice the first output without sleep() method. |work| is not printed but the thread count is shown to be 2. Does this mean main() thread execution ended after Thread.activeCount() but before |work| is printed? In third output seems like main() ended after execution of both these statements.
Now, I was never expecting Thread.activeCount() to be 2, since the daemon thread worker is joined on user thread main(), which means when Thread.activeCount() is executed, there will only be worker thread and no main() thread.
I don't know the exact details on how the VM knows when the last non-daemon thread stops running, but I can imagine 2 solutions:
a background regularly polls to see if all non-daemon threads have exited (and I doubt that's the actual solution)
a background thread joins on all the non-deamon threads, and exits the VM once all the join return
In those two situations, a race condition is possible, and the daemon thread sometimes has time to execute a few more operations after the main thread has died, and sometimes not.
I executed your code a few times, and sometimes something is printed after the main thread has exited, and sometimes not, which corroborates my theory.
When I add a Thread.sleep(100L) call after t.join(), nothing is printed except "Exit from main method".
Also note that if you look at the list of threads running in the VM (using the debugger for example), one of them is named "DestroyJavaVM". Given the name, I'd guess this is the thread which exits the JVM, concurrently to the remaining daemon threads, once the last non-daemon thread stops running.
How do you run your code?
When I run your example from command line I am getting:
Exit from main method
1
|work|
I guess you might not get activeCount and |work| printed out as JVM can just stop daemon-threads when all non-daemon threads terminated (the only one here is main thread). When that condition is met, JVM terminates remaining daemon threads and exits.
Thread javadoc says:
The Java Virtual Machine continues to execute threads until either of the following occurs:
The exit method of class Runtime has been called and the security manager has permitted the exit operation to take place.
All threads that are not daemon threads have died, either by returning from the call to the run method or by throwing an exception that propagates beyond the run method.
Terminating those threads might take some time though, so your daemon thread might have a chance to execute some more instructions. When I add Thread.sleep(1000) after printing activeCount, the activeCount is still printed, but |work| is not.
Let me first attempt to answer the outputs for
without Thread.sleep(1000)
Exit from main method 2 - You have to remember your Worker thread is a daemon so the JVM is not going to wait for it to complete its execution. It is only bothered about completing the main thread execution which is a non daemon.
Now you are getting this output because "Exit from Main Method" was shown by the main thread and in the meantime worker thread ran and displayed 2 but alas unfortunately the main thread completed and the JVM did not wait for the worker thread ( being a daemon) hence 'work' was not displayed.
Exit from main method 1 |work| - Here go with the same explanation as above
B U T the worker thread was lucky ..it got enough time to display '|work|'
before the JVM completed the main thread and hurried to its exit.
Exit from main method 2 |work| - Same as previous explanation...not sure
about why active count returns 2 sometimes and 1 sometimes.
You could use similar logic for coming to conclusions for the
With Thread.sleep(1000) logic.
Tip: Also you can check the status of thread t with statement
System.out.println("status of t : " + t.getState()); just before
t.join()....you will get TERMINATED a lot..which proves that the main thread
which is the NON DAEMON has already terminated so no question of join working...
too late...
I read this statement:
The main thread must be the last thread to finish execution. When the main thread stops, the program terminates.
Is it true?
I also came to know "Even if the main thread dies, the program keeps running".
This is my current understanding:
When you start a program, the JVM creates one thread to run your program.
The JVM creates one user thread for running a program. This thread is called main thread.
The main method of the class is called from the main thread.
If a program spawns new threads from the main thread, the program waits until the last thread dies.
Which one is true?
The program terminates when all non-daemon threads die (a daemon thread is a thread marked with setDaemon(true); it's usually used for utility threads). From the documentation:
When a Java Virtual Machine starts up, there is usually a single non-daemon thread (which typically calls the method named main of some designated class). The Java Virtual Machine continues to execute threads until either of the following occurs:
The exit method of class Runtime has been called and the security manager has permitted the exit operation to take place.
All threads that are not daemon threads have died, either by returning from the call to the run method or by throwing an exception that propagates beyond the run method.
I read this statement: “The main thread must be the last thread to finish execution. When the main thread stops, the program terminates.”Is it true?
No, it is not. The virtual machine terminates if the last non-daemon thread has finished. It doesn't have to be the main thread.
Simple example:
public static void main(String[] args) {
System.out.println("Main thread started");
new Thread(new Runnable() {
#Override
public void run() {
System.out.println("Second thread started");
try {
Thread.sleep(2000); // wait two seconds
} catch(Exception e){}
System.out.println("Second thread (almost) finished");
}
}).start();
System.out.println("Main thread (almost) finished");
}
When the main thread stops, the program terminates.
The program terminates when there no longer is any non-daemon thread running (or someone called System.exit). The main thread can have finished long ago.
The JVM will exit when the main thread and all non-daemon threads finish execution.
When you create a new thread, you can call Thread.setDaemon(true) to make it a daemon thread. If you do this, then the JVM will not wait until this thread finishes before execution. This is useful for any threads you create which are made to run in the background until the program stops.
If you create a new thread and do not call Thread.setDaemon(true), then the JVM will delay exit until this thread is complete, even if the main thread is finished.
When the main thread was start it'll not wait for the another thread which was created by us until they if can't use the join() of the thread class to wait for this thread. So basically if the child thread or sub thread getting more time for processing the task and you don't use the join() then main thread may be stop. To keep with main thread you must use the join() so the main thread stop after only this related thread are stop
check this link
http://download.oracle.com/javase/1.5.0/docs/api/java/lang/Thread.html#join%28%29
The first statementis not exact.
The java program terminates when all non-daemon threads has been terminated or when System.exit() or Runtime.exit() is invoked.
Thread is terminated when it exited its run() method. Main thread is special because you do not explicitly implement its run() method, you implement main() instead and the main() is called from run(). So, main thread is terminated when main() is terminated.
But main thread is not neccessarely the last one.
This is the from the JVM specification 3rd Draft, so it's the most current I'm aware of:
5.7 Virtual Machine Exit
The Java virtual machine terminates all its activity and exits when either:
• All threads that are not daemon threads terminate.
• Some thread invokes the exit method of class Runtime or class System, and
the exit operation is permitted by the security manager.
There is no distinction made about the main thread, so we shouldn't assume that is the only one that it applies to.
since main() runs on a thread. and as soon as the main() finishes, main-thread should stop. So if main() has invoked a long running thread which is yet to finish even after main() has done all the task. Since main() is returned, would the other threads be terminated? i guess no. but why?
public static void main(String[] s){
new LongRunningThread().start();
}
The process will terminate when there are no more non-daemon threads, killing any daemon threads if necessary. However, if you do have any non-daemon threads, those will prevent the process from terminating.
From Thread.setDaemon:
Marks this thread as either a daemon thread or a user thread. The Java Virtual Machine exits when the only threads running are all daemon threads.
This method must be invoked before the thread is started.
And from section 12.8 of the JLS:
A program terminates all its activity and exits when one of two things happens:
All the threads that are not daemon threads terminate.
Some thread invokes the exit method of class Runtime or class System, and the exit operation is not forbidden by the security manager.
if your long running thread is not a daemon thread, it will not get terminated once the main thread exits. The JVM continues to run threads until the exit method of Runtime is called (and permitted to run) or all non-daemon threads have died. If your long running thread is not a daemon thread, JVM will not exit (i.e. thread will continue to be available for running).
To answer your question why, it's because making your thread a non-daemon thread means that you don't want it to be terminated abruptly, you want it to be terminated in an orderly way by running to completion or by being canceled. If your thread was killed by the JVM once main was exited that would be equivalent to making the thread a daemon.
As currently executing thread while it encounters the call sleep() then thread moves immediately into sleeping stat.
Whereas for yield() thread moves into runnable state / ready state.
We can prevent a thread from execution by using any of the 3 methods of Thread class:
yield() method pauses the currently executing thread temporarily for giving a chance to the remaining waiting threads of the same priority or higher priority to execute. If there is no waiting thread or all the waiting threads have a lower priority then the same thread will continue its execution. The yielded thread when it will get the chance for execution is decided by the thread scheduler whose behavior is vendor dependent.
join() If any executing thread t1 calls join() on t2 (i.e. t2.join()) immediately t1 will enter into waiting state until t2 completes its execution.
sleep() Based on our requirement we can make a thread to be in sleeping state for a specified period of time (hope not much explanation required for our favorite method).
sleep() causes the thread to definitely stop executing for a given amount of time; if no other thread or process needs to be run, the CPU will be idle (and probably enter a power saving mode).
yield() basically means that the thread is not doing anything particularly important and if any other threads or processes need to be run, they should. Otherwise, the current thread will continue to run.
Sleep() causes the currently executing thread to sleep (temporarily cease execution).
Yield() causes the currently executing thread object to temporarily pause and allow other threads to execute.
Read [this] (Link Removed) for a good explanation of the topic.
Sleep causes thread to suspend itself for x milliseconds while yield suspends the thread and immediately moves it to the ready queue (the queue which the CPU uses to run threads).
Yield : will make thread to wait for the currently executing thread and the thread which has called yield() will attaches itself at the end of the thread execution. The thread which call yield() will be in Blocked state till its turn.
Sleep : will cause the thread to sleep in sleep mode for span of time mentioned in arguments.
Join : t1 and t2 are two threads , t2.join() is called then t1 enters into wait state until t2 completes execution. Then t1 will into runnable state then our specialist JVM thread scheduler will pick t1 based on criteria's.
Yield(): method will stop the currently executing thread and give a chance to another thread of same priority which are waiting in queue. If thier is no thread then current thread will continue to execute. CPU will never be in ideal state.
Sleep(): method will stop the thread for particular time (time will be given in milisecond). If this is single thread which is running then CPU will be in ideal state at that period of time.
Both are static menthod.
Yield: It is a hint (not guaranteed) to the scheduler that you have done enough and that some other thread of same priority might run and use the CPU.
Thread.sleep();
Sleep: It blocks the execution of that particular thread for a given time.
TimeUnit.MILLISECONDS.sleep(1000);
yield(): yield method is used to pause the execution of currently running process so that other waiting thread with the same priority will get CPU to execute.Threads with lower priority will not be executed on yield. if there is no waiting thread then this thread will start its execution.
join(): join method stops currently executing thread and wait for another to complete on which in calls the join method after that it will resume its own execution.
For detailed explanation, see this link.
One way to request the current thread to relinquish CPU so that other threads can get a chance to execute is to use yield in Java.
yield is a static method.
It doesn't say which other thread will get the CPU.
It is possible for the same thread to get back the CPU and start its execution again.
public class Solution9 {
public static void main(String[] args) {
yclass yy = new yclass ();
Thread t1= new Thread(yy);
t1.start();
for (int i = 0; i <3; i++) {
Thread.yield();
System.out.println("during yield control => " + Thread.currentThread().getName());
}
}
}
class yclass implements Runnable{
#Override
public void run() {
for (int i = 0; i < 3; i++) {
System.out.println("control => " + Thread.currentThread().getName());
}
}
}
sleep()causes the thread to definitely stop executing for a given amount of time; if no other thread or process needs to be run, the CPU will be idle (and probably enter a power saving mode).
yield()basically means that the thread is not doing anything particularly important and if any other threads or processes need to be run, they should. Otherwise, the current thread will continue to run.
sleep() causes the thread to definitely stop executing for a given amount of time; if no other thread or process needs to be run, the CPU will be idle (and probably enter a power saving mode).
yield() basically means that the thread is not doing anything particularly important and if any other threads or processes need to be run, they should. Otherwise, the current thread will continue to run.
Both methods are used to prevent thread execution.
But specifically,
sleep():
purpose:if a thread don't want to perform any operation for particular amount of time then we should go for sleep().for e.x. slide show .
yield():
purpose:if a thread wants to pause it's execution to give chance of execution to another waiting threads of same priority.thread which requires more execution time should call yield() in between execution.
Note:some platform may not provide proper support for yield() . because underlying system may not provide support for preemptive scheduling.moreover yield() is native method.