why does the main thread wait - java

In the below code, why does the main thread wait until the child thread is finished.
Driver.java
public class Driver {
public static void main(String[] args) throws InterruptedException {
Thread t = new Thread(new ThreadRunner());
t.start();
}
}
ThreadRunner.java
public class ThreadRunner implements Runnable {
#Override
public void run() {
for (int i = 0; i < 10; i++) {
System.out.println("Child thread" + i);
}
}
}
Here in the Driver class after calling 't.start()' shouldn't the program quit? I'm not using join but still the main thread waits until the newly spun 'ThreadRunner' run is running. Is it because in java the main thread (which is started by main method) always waits until all the threads are shut?

The main thread exits immediately after having started the other thread, but the Java program as a whole continues running as long as there are non-daemon threads alive (and unless you specifically request it, new threads will be non-daemon).
Making the thread a daemon thread is easy: simply call t.setDaemon(true); before starting it.

The main thread doesn't actually wait. The main thread completes. The program does not quit because you create a Thread that is non-daemon. The JVM will shut down when only daemon threads remain.

you can add 'System.out.println("main thread");' below 't.start()'
then you can see main thread is the first.

Related

Java Garbage Collection for Threads

How exactly does Java's garbage collection handle threads?
To clarify, I have a peer to peer network I'm writing in Java, and if a peer is determined to be acting maliciously or is rejected from the routing tables, I remove all references to the Peer object, which extends a thread.
Would I be correct in assuming that even though I deleted all references to the instance, the thread for that instance, and therefore the instance, would not be removed by the garbage collector?
No. It will not be collected or stopped while it is running.
You should stop your thread from within the thread, for example by using using the command return;.
Here is an experiment:
public class Main {
public static void main(String[] args) {
Runnable r = new Runnable(){
public void run() {
for (int i=0; i < 10; i++) {
System.out.println("Thread is running");
}
return;
}
};
Thread t=new Thread(r);
t.start();
t=null;
System.out.println("App finished");
}
}
Here is the result:
App finished
Thread is running
Thread is running
Thread is running
Thread is running
Thread is running
Thread is running
Thread is running
Thread is running
Thread is running
Thread is running
So, the thread was not stopped or collected even after the main thread set the reference to null and stopped working.

Which Thread is Sleeping in this code? Main Thread or t1 thread?

Generally Main thread starts first and then user threads starts, but in below code I am unable to figure out that main thread will sleep or t1 thread.
MessageGenerator.java
public class MessageGenerator implements Runnable {
String msg;
public MessageGenerator(String msg) {
super();
this.msg = msg;
}
#Override
public void run() {
System.out.println(Thread.currentThread().getName()+" Running");
System.out.println(msg);
}
}
MainClass.java
public class MainClass {
public static void main(String[] args) throws InterruptedException {
Thread t1=new Thread(new MessageGenerator("Hello"));
t1.sleep(5000); //Confused here
t1.start();
Thread t2=new Thread(new MessageGenerator("Hi"));
t2.start();
System.out.println(Thread.currentThread().getName()+" Running");
}
}
please reply
Thread.sleep(long millis) is a static method that lets the current thread (which is, the thread that this method is being called from) sleep for the specified number of milliseconds.
In the example you gave, the main thread will sleep for 5 seconds - not the thread that t1 refers to.
The code is misleading, because you are calling a static method on an instance.
Sleep is a static method of Thread class, it should be called as Thread.sleep(long millisec)
Causes the currently executing thread to sleep (temporarily cease execution) for the specified number of milliseconds, subject to the precision and accuracy of system timers and schedulers. The thread does not lose ownership of any monitors.
main thread will sleep ..for 5000 millisecond.
sleep() is a static method that always references the current executing thread.so it call on main thread so main thread will sleep.

Thread Join Method. Can main thread complete before other Threads?

I know how the thread join method works, but i have a sample question. Please see the example code below
public class RunnableJob implements Runnable{
#Override
public void run(){
Thread currentThread = Thread.currentThread();
System.out.println("Runnable job is run by" + currentThread.getName());
try{
Thread.sleep(1000);
}
catch(InterruptedException ie){
ie.printStackTrace();
}
}
}
public class ThreadExample{
public static void main(String[] args) throws InterruptedException{
RunnableJob runnableJob = new RunnableJob();
Thread thread1 = new Thread(runnableJob,"T1");
Thread thread2 = new Thread(runnableJob,"T2");
Thread thread3 = new Thread(runnableJob,"T3");
Thread thread4 = new Thread(runnableJob,"T4");
thread1.start();
thread1.join();
thread2.start();
thread2.join();
thread3.start();
thread3.join();
thread4.start();
thread4.join();
Thread thread5 = new Thread(runnableJob,"T5");
Thread thread6 = new Thread(runnableJob,"T6");
Thread thread7 = new Thread(runnableJob,"T7");
Thread thread8 = new Thread(runnableJob,"T8");
thread5.start();
thread6.start();
thread7.start();
thread8.start();
}
}
I know that, T1,T2,T3,T4 will block the main thread, before they complete. But is it possible that before T5,T6,T7,T8 actually start running, the main thread completes and T5..T8, remain in runnable state only. If this is possible, how can i produce the same?
Thanks.
The term you are looking for to answer your question is "daemon" threads. As long as there are non-daemon threads running, the application will not terminate and those threads will be able to run to a terminated state.
In your case, therefore, T5...T8 will run and complete as they are non-daemon threads †.
From the documentation for Thread:
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
† In fact the original single non-daemon thread started by the JVM may enter the terminated state before T5...T8 do. That will not stop T5...T8 running to completion in this case.

How can i make the main Thread as Daemon Thread in java?

I want to make the main thread as daemon thread but it show me IllegalThreadStateException.
Is there any way to do that?
public class DeamonThreads {
public static void main(String[] args) {
System.out.println("Main Started");
System.out.println("Thread type deamon = " + Thread.currentThread().isDaemon());
Thread.currentThread().setDaemon(true);
System.out.println("Thread type deamon = " + Thread.currentThread().isDaemon());
System.out.println("Main End");
}
}
Output
Main Started
Thread type deamon = false
Exception in thread "main" java.lang.IllegalThreadStateException
at java.lang.Thread.setDaemon(Thread.java:1367)
at com.threads.DeamonThreads.main(DeamonThreads.java:8)
The main thread cannot be set as daemon thread. Because a thread can be set daemon before its running and as soon as the program starts the main thread starts running and hence cannot be set as daemon thread.
As given in javadocs...
public final void setDaemon(boolean on)
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.
Parameters:
on - if true, marks this thread as a daemon thread
Throws:
IllegalThreadStateException - if this thread is alive
SecurityException - if checkAccess() determines that the current
thread cannot modify this thread.
As others already have pointed out, you can not do that, but what is the real problem that you want to solve?
There is nothing special about the main thread, so why not get rid of it? Would this work for you?
public static void main(String[] args) {
...create at least one non-daemon thread...
Thread t = new Thread(() -> {
daemon_main(args);
});
t.setDaemon(true);
t.start();
}
public static void daemon_main(String[] args) {
...do whatever else main() did...
}

Why UserThread running with ScheduleExecutorService does not get garbage collected

Please help me find the reason for Thread leak in the code below. The TestThread does not get garbage collected even after run() has completed (verified from the consoled print statement) and the main method has exited (verified from print statement and profiler tool).
The TestThread, however, gets garbage collected if it is set as a Daemon Thread i.e. t.setDaemon(true). The code below is just a sample code which illustrates the problem in my application. I'm trying to use some pre-existing scheduling class (which was designed by someone else using ScheduledExecutorService). I notice that when I keep scheduling multiple Runnables with the class, the created threads never get garbage collected.
public class ThreadTest {
static void runThreadWithExecutor() {
final String name = "TestThread";
ScheduledExecutorService ses = Executors.newSingleThreadScheduledExecutor(
new ThreadFactory() {
#Override
public Thread newThread(Runnable r) {
Thread t = new Thread(r, name);
t.setDaemon(false);
return t;
}
});
ses.schedule(new Runnable() {
#Override
public void run() {
System.out.println("entered " + name);
System.out.println("exiting " + name);
}},
2,
TimeUnit.SECONDS);
}
public static void main(String[] args) throws InterruptedException {
System.out.println("entered main");
runThreadWithExecutor();
Thread.sleep(5000);
System.out.println("exiting main");
}
}
This is due to the fact that you are not calling shutdown() on your executor service after you have scheduled your last job:
ses.schedule(...);
// this stops any management threads but existing jobs will still run
ses.shutdown();
I just added the shutdown() call to your code and it exits fine. This is true of all ExecutorServices. Without the shutdown the thread pool continues to wait for more jobs to be submitted and is never GC'd.
See #John's answer below for more details.
#Gray is correct with his assessment I just figure I add the why he is correct. The ExecutorService is a thread-pool which will reuse the threads.
Unlike new Thread(runnable).start(); when the run method completes the thread completes and will then be GC'd. When an Executor Runnable completes the thread will sit there and wait for another runnable task to be submitted and used. So by shutting down you are telling the executor to end all of the Threads in the thread pool.
To answer your last part. Setting it to daemon works only because there are no other (non-daemon) threads running. If your application started some other non daemon thread the Executor thread's will continue. Remember a daemon thread will be killed when only daemon threads are running.

Categories