Why isn't there a daemon thread that joins the main () thread of threads when the main () thread finishes?

In the code below:

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 the worker is a daemon thread associated with the main () thread, | work | should never be printed, since the user's main () thread exits first, and since the worker is a daemon thread, it also stops when the main () thread dies. But I get this: Exit from main method 1 | Work |

Please clarify this request for me.

After many many executions of the program, I have seen the following different outputs:

without Thread.sleep (1000):

Exit from main method 2

Exiting the main method 1 | Work |

Exiting the main method 2 | Work |

with Thread.sleep (1000):

Exiting the main method 2 | Work |

Exiting the main method

Notice the first exit without sleep () method. | Works | is not printed, but the number of threads is shown as 2. Does this mean that the execution of the main () thread finished after Thread.activeCount (), but before | work | printed? On the third output, it appears that main () has completed after both of these statements have been executed.

Now I never expected Thread.activeCount () to be 2 as the daemon worker thread is connected to the user thread main () which means when Thread.activeCount () is executed there will only be a worker thread and no main () thread ...

+3


source to share


3 answers


I don't know the exact details of how the VM knows when the last non-daemon thread stops working, but I can think of 2 solutions:

  • background polling regularly to see if all non-daemon threads have exited (and I doubt the actual solution)
  • background thread attaches to all non-deamon threads and exits the VM after all connection returns

In these two situations, a race condition is possible, and the daemon thread sometimes manages to perform several more operations after the main thread has died, and sometimes not.



I have executed your code several times and sometimes something prints after the main thread exits and sometimes it doesn't, which confirms my theory.

When I add the call Thread.sleep(100L)

after t.join()

, nothing is printed except "Exit main method".

Also note that if you look at the list of threads running in the virtual machine (for example, using the debugger), one of them is called "DestroyJavaVM". Given the name, I would assume it is a thread that exits the JVM at the same time as the rest of the daemon threads after the last non-daemon thread stops running.

+2


source


How do you run your code?

When I run your example from the command line, I get: Exit from main method 1 | Work |

I think you cannot type activeCount

and |work|

as the JVM can just stop daemon-threads when all non-daemon threads have finished (the only thread here main

). When this condition is met, the JVM terminates the remaining daemon threads and exits.



Thread

javadoc says:

The Java Virtual Machine continues to execute threads until one of the following occurs:

  • The exit method of the Runtime class is called, and the security manager has authorized the exit operation.
  • 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 outside of the run method.

It may take a while for these threads to complete, so your daemon thread may have a few more instructions to execute. When I add Thread.sleep(1000)

after printing activeCount

, activeCount

it still prints but |work|

not.

0


source


Let me first try to answer the outputs for

without Thread.sleep (1000)

Exit Main Method 2 - You have to remember that your worker thread is a daemon, so the JVM does not wait for it to complete. It only bothers execution of the main thread, which is not a daemon. Now you get this result because "Exit main method" was shown by the main thread and meanwhile the worker thread was running and displayed 2, but unfortunately the main thread was terminated and the JVM did not wait for the worker thread (being a daemon). therefore "work" was not displayed.

Exiting the main method 1 | work | - Here are the same explanations as above BUT, the worker thread is lucky .. it has enough time to display '| work | ' before the JVM finished the main thread and rushed to its exit.

Exiting the main method 2 | work | - Same as the previous explanation ... not sure about why the active counter returns 2 sometimes and 1 sometimes.

You can use similar logic to output to output

With logic Thread.sleep (1000).

Council. You can also check the status of stream t with the System.out.println instruction ("t status:" + t.getState ()); right before t.join () .... you will get TERMINATED a lot. This proves that the main thread, which is a NON DAEMON, is already ending, so there is no question of joining the work ... too late ...

0


source







All Articles