I need to create a daemon in Java which periodically retrieves data via HTTP and stores that in a database.
When the main thread starts up, it reads the data sources and poll intervals from a configuration file and creates a TimerTask with the appropriate interval for each data source. In addition, it calls Runtime.getRuntime().addShutdownHook() to add a shutdown hook which performs any cleanup needed before shutdown. After that, the main thread has nothing else to do.
The daemon is intended for use in a classic Unix environment, i.e. controlled with a start/stop script, though it should be portable to other OSes (say, Windows with SrvAny).
How would I go about this? If I just let the main thread exit, will the TimerTask instances keep the VM running until all of them have been cancelled? If not, how would I accomplish this?
Threads in Java have a flag to indicate if they should keep the jvm alive or not. This flag is called "daemon": the jvm will exit when only daemon threads are running.
The thread started by Timer is not a daemon thread by default, so it will keep the jvm alive, which is what you want. If you wanted the jvm to exit, you could create the timer with new Timer(true) - this would set the daemon flag. https://docs.oracle.com/javase/10/docs/api/java/util/Timer.html#%3Cinit%3E(boolean)
It depends on the Timer on which the TimerTask was scheduled: if that Timer was created not to run its tasks as daemons, a pending TimerTask will keep the VM alive even after the main thread has finished its work. This is the case for all Timer constructors which do not take a boolean argument, or where the boolean argument is false.
The following seems to work as intended:
package com.example.daemon;
import java.util.Date;
import java.util.Timer;
import java.util.TimerTask;
public class SampleDaemon {
private static Timer testTimer = new Timer(false);
public static void main(String[] args) {
Runtime.getRuntime().addShutdownHook(new Thread() {
#Override
public void run() {
System.out.println("Received shutdown request!");
if (testTimer != null)
testTimer.cancel();
testTimer = null;
}
});
testTimer.schedule(new TestTimerTask(), new Date(), 2000);
}
private static class TestTimerTask extends TimerTask {
#Override
public void run() {
System.out.println("Still running…");
}
}
}
It prints Still running… every 2 seconds. When the JVM receives a SIGTERM, the program prints Received shutdown request! and exits. This can also be accomplished by sending Ctrl+C from the console. SIGHUP does the same as SIGTERM.
SIGCONT has no effect; SIGUSR1 results in a hard exit (presumably the same as SIGKILL), i.e. without executing the shutdown hook.
Related
I have a web app which runs an interface for controlling an irrigation system. The system starts up to 10 or so threads, using a ScheduledThreadPoolExecutor.
I have found that when I close down the server, many of these threads continue to run. From the Tomcat catalina.out log:
org.apache.catalina.loader.WebappClassLoaderBase.clearReferencesThreads The web application [GH2] appears to have started a thread named [pool-2-thread-1] but has failed to stop it. This is very likely to create a memory leak.
The classes that start these threads are dotted around my app. In order to try to have some control over stopping them, I have a single ScheduledThreadPoolExecutor created by a ServletContextListener and passed into each of the classes that might start a task.
I have tried setting properties in the ScheduledThreadPoolExecutor that I assumed would close down all threads when contextDestroyed() is called in the listener:
public void contextInitialized(ServletContextEvent event) {
executor = (ScheduledThreadPoolExecutor) Executors.newScheduledThreadPool(10);
executor.setContinueExistingPeriodicTasksAfterShutdownPolicy(false);
executor.setExecuteExistingDelayedTasksAfterShutdownPolicy(false);
executor.setRemoveOnCancelPolicy(true);
event.getServletContext().setAttribute("executor", executor);
Here is a typical bit of code that schedules a thread:
public WeatherScheduler(ScheduledThreadPoolExecutor executor) {
this.executor = executor;
checkEveryHour();
}
public void checkEveryHour() {
final Runnable weatherChecker = new Runnable() {
public void run() {
if (!Thread.interrupted()) {
if (Date_TimeUtils.isBetween7amAnd8pm()) {
weather = new Weather();
weather.getNewForecast();
IrrigationLogger.getInstance().logEvent("weather forecast: " + weather.toString());
} else
LOGGER.log(Level.INFO, "weatherChecker not called as isBetween7amAnd8pm() == false ");
}
}
};
// delay of a minute to allow for getting internet connection, repeat every hour
executor.scheduleAtFixedRate(weatherChecker, 1, 60, TimeUnit.MINUTES);
}
When the server is closed down, the contextDestroyed() method is called in the listener, and I have
executor.shutdownNow();
included in that method.
But still I get the message in the log file that threads have been started that can't be stopped.
What am I missing?
Thanks.
The way any ThreadExecutor tries to stop a currently running thread is by setting interrupt flag by invoking Thread class method interrupt() on that thread. It is responsibility of the running thread to detect that it was "asked" to finish, so the running thread should clean up and terminate once the signal received. So first in your runner code surround it with try-catch where you will catch InterruptedException and also in your runner code you suppose to invoke method Thread.currentThread().isInterrupted() and if it returns true clean up and finish the thread (same as in your catch statement)
I have code that schedules one-time tasks to execute and does this over and over. It looks something like this.
public static void main(String[] args)
{
while(true)
{
....
TimerTask closeTask = new CloseTask(cli);
Timer timer = new Timer(true);
timer.schedule(closeTask, (long) (iPeriod * 60 * 1000));
...
}
}
public class CloseTask extends TimerTask
{
Client client;
CloseTask(Client in_client)
{
client = in_client;
}
public void run()
{
try
{
for(int iRetries = 0; state == OPEN; iRetries++)
{
logger.log_trade_line_grablock( "Thread " + Thread.currentThread().getId() + ": About to send message", true, true, true, true, true);
client.send_mesg("close");
logger.log_trade_line_grablock( "Waiting 5 seconds before retrying ", true, true, true, true, true);
Thread.sleep(5000);
}
}
catch (Exception e)
{
e.printStackTrace();
}
}
}
The intent of the run() method in the CloseTask class is to loop until the state variable changes from OPEN state to something else. However, intermittently the timer threads simply disappear, while state still equals OPEN, which I know by printing out all the thread ID's of the currently running threads every 5 minutes.
So my questions:
1) The only explanation I can think of is that the CloseTask object is throwing uncaught exceptions. Is that correct?
2) If 1) is correct why isn't my try catch block catching these exceptions?
3) If 1) is correct is there a way to catch these exception that slip through uncaught?
Thanks for any insight into this issue.
You're creating a Timer instance, but not making sure that it doesn't get garbage collected.
From the documentation:
After the last live reference to a Timer object goes away and all outstanding tasks have completed execution, the timer's task execution thread terminates gracefully (and becomes subject to garbage collection).
So basically, you need to hold on to the reference to the Timer you created instead of just using a local variable.
The boolean you are passing in tells whether or not the thread created will be daemon. If it is daemon, the thread will be stopped once all non-daemon threads are finished. Since the only non-daemon thread being run in your application is the main thread then it will immediately be stopped after the main method is completed.
As Jon Skeet mentioned there is some completion operations done if no live thread is referencing the Timer and the tasks complete, but if it's daemon and the main method completes, it may not exit gracefully. To continue the documentation
... However, this can take arbitrarily long to occur. By default, the task execution thread does not run as a daemon thread, so it is capable of keeping an application from terminating. If a caller wants to terminate a timer's task execution thread rapidly, the caller should invoke the timer's cancel method.
To answer your question
The only explanation I can think of is that the CloseTask object is throwing uncaught exceptions. Is that correct?
If the JVM kills a non-daemon thread, it won't throw any exception. So you won't really know that it happened.
My web application (on Tomcat) provides “on the fly” logic execution functionality.
The problem is the “on the fly” logic can contains infinite loop , or something long duration.
My solution is timeout: to run the “on the fly” logic in a new daemon thread and go back main thread in timeout, p-code as below:
ExecutorService executor = Executors.newSingleThreadExecutor(new ThreadFactory(){
#Override
public Thread newThread(Runnable r) {
Thread t = new Thread(r);
result.setDaemon(true);
return t;
}});
Future<Object> future = executor.submit(callable/* 'on the fly' callable: it can be infinite loop, the callable is out of my control */);
//Back to main thread
return future.get(timeout, TimeUnit.MILLISECONDS);
However, the daemon thread is still running, although future.get() returns in timeout. The daemon is terminated until Tomcat stops.
Now my latest solution is create a new Java process Runtime.getRuntime().exec("java MyProgram"). MyProgram contains future.get() shown before. The daemon is terminated once main thread quits as expected.
I am here to ask more elegant solution to terminate thread in web application. The new Java process is heavy and out control of web application.
Thanks!
threading in a managed environment is generally a bad idea. why not use some sort of abstraction like JMS to start a background handler every time someone sends a request ? that way you can control the number of active threads (jms pool size)
We use Hazelcast 2.6.2 in a legacy Java clustered application. When the application is stopped the JVM does not terminate any more. It seems that it is caused by Hazelcast threads not being flagged daemon. I did not find a way way through the Hazelcast API to flag them daemon.
Are there recommended solutions to prevent Hazelcast from preventing the JVM to terminate?
Regards
Looking at the Hazelcast Javadocs, I see that there is a shutdownAll(); method. To quote the javadocs:
Shuts down all running Hazelcast Instances on this JVM, including the default one if it is running. It doesn't shutdown all members of the cluster but just the ones running on this JVM.
If you aren't shutting it down I suspect there are non-daemon threads there that aren't being terminated that will keep the JVM from closing.
In Tomcat, I added a lifecycle listener via server.xml.
<Listener className="com.mycompany.StartupHandler" DEBUG="false"/>
My StartupHandler.class went in a jar in $TOMCAT_HOME/lib/, and it contains this snippet to trigger Hazelcast shutdown when Tomcat shutdown is detected:
public void lifecycleEvent(LifecycleEvent lifecycleEvent) {
String eventType = lifecycleEvent.getType();
if (eventType.equals(Lifecycle.BEFORE_STOP_EVENT)) {
com.hazelcast.core.Hazelcast.shutdownAll();
}
}
Other web servers should have similar shutdown hooks where you can invoke Hazelcast.shutdownAll() automatically.
See https://github.com/hazelcast/hazelcast/issues/718 for my original Hazelcast thread on the same topic. Thanks for the hint here to call Hazelcast.shutdownAll(). That idea combined with my Tomcat shutdown hook should be sufficient to resolve this problem for me, and hopefully you find it useful too.
Here is a Tomcat independent way to detect JVM shutdown. It uses a non-daemon thread to poll a daemon thread to detect when the JVM is shutting down (the JVM shuts down daemon threads automatically). Poll the static IS_SHUTDOWN flag in your code, or inline the call to Hazelcast.shutdownAll() here. Be careful of a race condition, because if you try to shutdown Hazelcast before it starts then it throws an exception in your log. The exception does not break anything, but it looks ugly.
/**
* Non-Daemon thread monitors a sacrificial, low-priority, daemon thread
* to detect when JVM is shutting down, so shutdown hooks can be invoked.
* #author justin.cranford
*/
public class ThreadUtil {
public static boolean IS_SHUTDOWN = false; // threads can poll this flag, or inline below where flag is set
private static final Thread DAEMON_THREAD = new Thread() {
public void run() {
while (true) {
try {
Thread.sleep(Long.MAX_VALUE); // sleep forever
} catch(Exception e) {}
}
}
};
private static final Thread NONDAEMON_THREAD = new Thread() {
public void run() {
while (true) {
if (!DAEMON_THREAD.isAlive()) { // poll forever, until daemon thread dies
ThreadUtil.IS_SHUTDOWN = true;
return;
}
try {
Thread.sleep(1000); // poll every 1000msec = 1sec
} catch(Exception e) {}
}
}
};
static {
DAEMON_THREAD.setName("ShutdownMonitorNonDaemonThread");
DAEMON_THREAD.setPriority(Thread.MIN_PRIORITY);
DAEMON_THREAD.setDaemon(true);
DAEMON_THREAD.start();
try {
Thread.sleep(3000); // wait 3000msec = 3sec before monitoring
} catch(Exception e) {}
NONDAEMON_THREAD.setName("ShutdownMonitorDaemonThread");
NONDAEMON_THREAD.setPriority(Thread.MIN_PRIORITY);
NONDAEMON_THREAD.setDaemon(false);
NONDAEMON_THREAD.start();
}
}
As everyone said, hazelcastInstance.shutdownAll() is the solution.
But, I would to get a new feature in Hazelcast - provide a demon client as well. There are many use cases where cache instance needs to be shutdown as soon as application ends.
I'm getting some exception and I need to know when the program closes itself because I need to close the socket.
I have the default public static main method where I'm keep repeating an action and a Thread class.
private static Thread thread;
public static boolean isRunning = true;
public static void main(String[] args){
thread = new Thread(new ThreadListenServer());
thread.start();
Timer timer = new Timer();
TimerTask task = new TimerTask() {
#Override
public void run(){
// some action
}
}
timer.scheduleAtFixedRate(task, 0, 10000);
isRunning = false;
}
And the thread class which is running in background:
public class ThreadListenServer implements Runnable{
private DatagramSocket socket;
public ThreadListenServer() throws SocketException{
socket = new DatagramSocket(6655);
}
#Override
public void run() {
while(MainProgram.isRunning){
// some action
}
socket.close();
}
}
I don't know why, but isRunning it's becoming false, but it shouldn't. How am I supposed to close the socket if the main program was closed? (It's causing because the Thread still running in the background even if the program was closed).
I was thinking about to create the socket in the main class then I pass the socket object as a parameter to the ThreadClass and if the program is closed, than I should close the socket as well.
Use:
thread.setDaemon(true);
This will shut the thread. It tells the JVM it is a background thread , so it will shut down on exit.
Ill take the assumption you have a JFrame of some sort running as the class MainProgram. You have 2 options
1: set your Jframe to close all threads when it is closed.
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
2: add a window listener and manually close your thread (maybe you have to send some information across the socket before you close it)
addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent e) {
// send your socket its close message and shut everything down
System.exit(0);
}
});
To stop all Threads when your program exits cleanly, you'll need to define a termination policy for each Thread that gets started. This is normally done using Interrupts and ExecutorService.shutdownNow() method sends an interrupt to each running thread.
A clean termination policy consists to two parts:
Sending stop signal to thread – aka interrupting it
Designing threads to act on interruption
A thread in Java could be interrupted by calling Thread.interrupt() method. Threads can check for interruption by calling Thread.isInterrupted() method. A good thread must check for interruption at regular intervals, e.g. as a loop condition and checking blocking functions for InterruptedExceptions.
It is important to note that Sockets in Java are oblivious to interruption. For example, if a Thread is blocked on Socket.accept(), it will not throw InterruptedException when the Thread is interrupted. In this case, you need to define a public method which closes the underlying socket by calling Socket.close() forcing the blocking function to throw an Exception (I guess SocketException).
A few things come to mind.
It would appear you are performing a blocking I/O operation using sockets. You may need to interrupt either the running thread and/or the socket to get it to stop blocking
You should set the thread as daemon thread before it is started, using setDaemon(true). This will allow the JVM to terminate the thread automatically...
isRunning should be marked volatile or you should use AtomicBoolean instead