
net.sf.eBus.util.ShutdownHook Maven / Gradle / Ivy
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 2.1 of the License, or (at your option) any later
// version.
//
// This library is distributed in the hope that it will be
// useful, but WITHOUT ANY WARRANTY; without even the implied
// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
// PURPOSE. See the GNU Lesser General Public License for more
// details.
//
// You should have received a copy of the GNU Lesser General
// Public License along with this library; if not, write to the
//
// Free Software Foundation, Inc.,
// 59 Temple Place, Suite 330,
// Boston, MA
// 02111-1307 USA
//
// The Initial Developer of the Original Code is Charles W. Rapp.
// Portions created by Charles W. Rapp are
// Copyright (C) 2013. Charles W. Rapp.
// All Rights Reserved.
//
package net.sf.eBus.util;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
/**
* Provides a simple way for an console-based, Java application
* main thread to wait until the virtual machine terminates. If
* an application main method is solely responsible for setting
* up and tearing down the application and hands off control to
* another thread between the two, then the main thread must
* block until it is time to stop. This class is a Java
* {@link java.lang.Runtime#addShutdownHook(java.lang.Thread) shutdown hook},
* returning a {@link java.util.concurrent.CountDownLatch} on
* which the main thread waits. This latch is decremented when
* the Java {@code Runtime} executes the shutdown hook. Since the
* latch is size one, {@link CountDownLatch#await()} will return.
*
* This returned latch may be passed to other objects which can
* decrement the latch and so signal that the application is to
* terminate.
*
*
* An example Java main method uses this class as follows:
*
*
*
* import java.util.concurrent.CountDownLatch;
*
* public static void main(final String args[])
* {
* // 1. Check the command line arguments.
* // 2. Initialize the application.
* // 3. Set up the shutdown hook.
* final CountDownLatch signal = ShutdownHook.addShutdownHook();
*
* // 4. Start application thread.
* // 5. Wait for the JVM to stop.
* try {
* signal.await();
* } catch (InterruptedException interrupt) {}
*
* // 6. Tear down the application.
* }
*
*
*
* @author Charles Rapp
*/
public final class ShutdownHook
extends Thread
{
//---------------------------------------------------------------
// Member methods.
//
//-----------------------------------------------------------
// Constructors.
//
/**
* Creates a new JVM shutdown hook using the given signal.
* @param signal when the JVM is shutting down, decrement
* this signal.
*/
private ShutdownHook(final CountDownLatch signal)
{
_signal = signal;
} // end of ShutdownHook(CountDownLatch)
//
// end of Constructors.
//-----------------------------------------------------------
//-----------------------------------------------------------
// Thread Method Overrides.
//
/**
* Decrements the signal which results in a return from
* {@link CountDownLatch#await()}.
*/
@Override
public void run()
{
_signal.countDown();
return;
} // end of run()
//
// end of Thread Method Overrides.
//-----------------------------------------------------------
/**
* Returns the signal used by the shutdown hook to notify
* the caller when the JVM is shutdown. If the shutdown hook
* does not exist, then creates it and adds it to the
* default system runtime. The count down latch size is one,
* which means that {@link CountDownLatch#await()} returns
* as soon as this latch is decremented.
* @return the shutdown hook signal.
*/
public static CountDownLatch addShutdownHook()
{
CountDownLatch retval;
_lock.lock();
try
{
if (_instance != null)
{
retval = _instance._signal;
}
else
{
retval = new CountDownLatch(1);
_instance = new ShutdownHook(retval);
(Runtime.getRuntime()).addShutdownHook(
_instance);
}
}
finally
{
_lock.unlock();
}
return (retval);
} // end of addShutdownHook()
/**
* Unhooks the shutdown hook instance from the system
* runtime.
*/
public static void removeShutdownHook()
{
_lock.lock();
try
{
if (_instance != null)
{
(Runtime.getRuntime()).removeShutdownHook(
_instance);
_instance = null;
}
}
finally
{
_lock.unlock();
}
return;
} // end of removeShutdownHook()
//---------------------------------------------------------------
// Member data.
//
/**
* When the JVM is shutting down, decrement this signal.
*/
private final CountDownLatch _signal;
//-----------------------------------------------------------
// Statics.
//
/**
* The singleton shutdown hook instance.
*/
private static ShutdownHook _instance = null;
/**
* The lock protecting access to {@link #_instance}.
*/
private static final Lock _lock = new ReentrantLock();
} // end of class ShutdownHook
© 2015 - 2025 Weber Informatics LLC | Privacy Policy