Termination of Program on Main Thread Exit

termination of program on main thread exit?

No.

Java programs terminate when all non-daemon threads finish.

The documentation states:

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.

If you don't want the runtime to wait for a thread, call the setDaemon method.

Is it OK that child thread terminated when main thread exit in Ruby?

When the main thread exits, the process terminates and it stops all the other running threads. To avoid that, you can call Thread#join that waits for the other thread.

thread = Thread.new {
(1..10).each do |e|
`curl http://localhost/#{e}`
end
}

thread.join

Webservers processes most probably won't exit, but they may finish serving a request before the thread ends fetching the URL. It may be better to use a background processing tool to handle that case.

How to terminate a thread when main program ends?

Check this question. The correct answer has great explanation on how to terminate threads the right way:
Is there any way to kill a Thread in Python?

To make the thread stop on Keyboard Interrupt signal (ctrl+c) you can catch the exception "KeyboardInterrupt" and cleanup before exiting. Like this:

try:
start_thread()
except (KeyboardInterrupt, SystemExit):
cleanup_stop_thread()
sys.exit()

This way you can control what to do whenever the program is abruptly terminated.

You can also use the built-in signal module that lets you setup signal handlers (in your specific case the SIGINT signal): http://docs.python.org/library/signal.html

When the main thread exits, do other threads also exit?

When the main thread returns (i.e., you return from the main function), it terminates the entire process. This includes all other threads. The same thing happens when you call exit. You can avoid this by calling pthread_exit.

The purpose of pthread_detach is to make it so you don't need to join with other threads in order to release their resources. Detaching a thread does not make it exist past process termination, it will still be destroyed along with all the other threads.

Why the main thread doesn't terminate when there is a completion stage that has not been completed?

I added time marks to the output of your program and also a shutdown hook so that JVM termination can be logged as well:

0s Hello from thread: main              # `main` method starts
0s I am in the thread: pool-1-thread-1 # `Runnable` submitted to the executor starts
0s I am dying ... # `main` method exits
50s I am done, and my value is 6 # `Runnable` submitted to the executor finishes
110s exiting # JVM process exits

Non-daemon threads

The reason why the process continues after main method exits is that JVM needs to wait for all non-daemon threads to terminate before it shuts down. Executors produced using Executors class create non-daemon threads by default (see Executors.defaultThreadFactory() method javadoc).

Customizing ThreadFactory

You can override how the threads are created by passing a custom ThreadFactory to the Executors.newCachedThreadPool() method:

ExecutorService executorService = Executors.newCachedThreadPool(runnable -> {
Thread t = new Thread(runnable);
t.setDaemon(true);
return t;
});

executorService will only have daemon threads in its thread pool.

Thread caching

But notice that the JVM still doesn't exit for 60 seconds after your thenAccept block is executed:

50s I am done, and my value is 6        # `Runnable` submitted to the executor finishes
110s exiting # JVM process exits

Why is that? It's explained in Executors.newCachedThreadPool() documentation (emphasis added):

Creates a thread pool that creates new threads as needed, but will reuse previously constructed threads when they are available. These pools will typically improve the performance of programs that execute many short-lived asynchronous tasks. Calls to execute will reuse previously constructed threads if available. If no existing thread is available, a new thread will be created and added to the pool. Threads that have not been used for sixty seconds are terminated and removed from the cache. Thus, a pool that remains idle for long enough will not consume any resources. Note that pools with similar properties but different details (for example, timeout parameters) may be created using ThreadPoolExecutor constructors.

This means that this thread pool does not dispose of the threads immediately after they finish doing scheduled tasks. It will instead do it's best to reuse previously created threads for new task submissions. This is the reason for the delay: after your task finishes the thread remains in the thread pool for reusal and only after the next 60 seconds it is destroyed (you only submit one task in your program). Only then the JVM can exit (because the thread is not a daemon thread as pointed above).

Shutting down the ExecutorService

Normally when working with an ExecutorService you should shut it down explicitly before the process is terminated. For this purpose use ExecutorService.shutdown() or ExecutorService.shutdownNow() methods. Refer to the documentation for the difference between these two.

References

What is a daemon thread in Java?

Turning an ExecutorService to daemon in Java

Program does not terminate immediately when all ExecutorService tasks are done

Modified program with time marks and JVM termination log:

public class Main {
private static final Instant start = Instant.now();

private static void debug(String message) {
System.out.println(Duration.between(start, Instant.now()).getSeconds() + "s " + message);
}

public static void main(String[] args) {
Runtime.getRuntime().addShutdownHook(new Thread(() -> debug("exiting")));
debug("Hello from thread: "+Thread.currentThread().getName());
new Game().run();
debug("I am dying ... ");
}

static class Game {
public void run() {
value();
}

private int value() {
int number = 0;
CompletionStage<Void> c = calculate().thenApply(i -> i + 3).thenAccept(i -> debug("I am done, and my value is " + i));
return number;
}

private CompletionStage<Integer> calculate() {
CompletionStage<Integer> completionStage = new CompletableFuture<>();
Executors.newCachedThreadPool().submit(() -> {
debug("I am in the thread: " + Thread.currentThread().getName());
try {
Thread.sleep(50000);
((CompletableFuture<Integer>) completionStage).complete(3);
} catch (Exception e) {
e.printStackTrace();
}
return null;

});
return completionStage;
}
}
}

Run a method on main thread/program termination?

As user:Mad Programmer mentioned above, you could use ShutdownHook.

public static void main(String[] args) 
{
ShutdownHookThread shutdownHook = new ShutdownHookThread();
Runtime.getRuntime().addShutdownHook(shutdownHook );
}

private static class JVMShutdownHook extends Thread
{
public void run()
{
// tempDirectory.delete();
}
}

will main thread exit before child threads complete execution?

Java makes a distinction between a user thread and another type of thread known as a daemon thread. The difference between these two types of threads is that if the JVM determines that the only threads running in an application are daemon threads (i.e., there are no user threads), the Java runtime closes down the application. On the other hand, if at least one user thread is alive, the Java runtime won't terminate your application.

When your main() method initially receives control from the Java runtime, it executes in the context of a user thread. As long as the main-method thread or any other user thread remains alive, your application will continue to execute.

In your case, the threads are user threads and hence are allowed to complete before the main thread exits.

i am processing some files. in testA thread A alone, 1 file alone is
not getting processed some times. but many times

The reason for the above is could be something else than thread exits. It could be file locks, synchronization issue etc.

Thread (Java SE 10 & JDK 10):

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.


Related Topics



Leave a reply



Submit