All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.xqbase.util.Service Maven / Gradle / Ivy

There is a newer version: 0.2.18
Show newest version
package com.xqbase.util;

import java.util.Queue;
import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.Executor;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.atomic.AtomicBoolean;

/**
 * Create a Windows or Linux service, which can be stopped gracefully.

* * A Java program running as a service, whether in Windows or Linux, can be written as: * *


 *	private static Service service = new Service();
 *
 *	public static void main(String[] args) {
 *		if (!service.startup(args)) {
 *			return;
 *		}
 *		// initialize
 *		...
 *		while (!Thread.interrupted()) {
 *			// keep service running
 *			...
 *		}
 *		// close resources
 *		...
 *		service.shutdown();
 *	}
 * 
* * A Windows service is usually made with the service runner of * Apache Commons Daemon. * The service runner will call main method with an argument "stop" * in another thread to notify shutdown, which can be caught by {@link #startup(String[])}. * So the Service object must be a singleton.

* * A Linux service may receive SIGTERM (kill) and start the JVM's shutdown hook. */ public class Service implements Executor { CountDownLatch latch = new CountDownLatch(1); ExecutorService executor = Executors.newCachedThreadPool(); AtomicBoolean interrupted = new AtomicBoolean(false); Queue shutdownHooks = new ConcurrentLinkedQueue<>(); Queue closeables = new ConcurrentLinkedQueue<>(); private Thread shutdownHook = new Thread() { @Override public void run() { interrupted.set(true); Runnable runnable; while ((runnable = shutdownHooks.poll()) != null) { runnable.run(); } AutoCloseable closeable; while ((closeable = closeables.poll()) != null) { try { closeable.close(); } catch (Exception e) {/**/} } Runnables.shutdownNow(executor); try { latch.await(); } catch (InterruptedException e) { Thread.currentThread().interrupt(); } } }; /** * Execute a {@link Runnable} in the thread pool (created by the service).

* * This runnable will be interrupted when the service is stopping. */ @Override public void execute(Runnable command) { executor.execute(command); } /** * Start or stop the service according to: *

*
A. If the argument is "stop", it may be a stop notification * by the service runner and the shutdown hook will be started.
*
B. If the main method is not called by the service runner * (the main method is on the top of stack trace), * it will add a shutdown hook to catch SIGTERM.
*
C. Otherwise (may be called by the service runner) it will do nothing.
*
* * @param args arguments in the main method * @return false for case A and true for case B or C */ public boolean startup(String[] args) { if (args != null && args.length > 0 && args[0].equals("stop")) { shutdownHook.run(); return false; } // Do not call addShutdownHook inside Apache Commons Daemon Service Runner if (new Throwable().getStackTrace().length == 2) { Runtime.getRuntime().addShutdownHook(shutdownHook); } return true; } /** * The shutdown hook will be suspended until shutdown() is called. * This can prevent the main thread being killed before closing resources. */ public void shutdown() { latch.countDown(); } /** * Enforce to stop the service. */ public void shutdownNow() { if (!isInterrupted()) { Runtime.getRuntime().removeShutdownHook(shutdownHook); shutdownHook.start(); } } /** * Check whether the service is stopping.

* * In the main thread, this can be replaced with Thread.interrupted() or * Thread.currentThread().isInterrupted(). * * @return true when the service is stopping */ public boolean isInterrupted() { return interrupted.get(); } /** * Add a {@link Runnable} (NOT the JVM's shutdown hook) into the queue * which will be run when the service is stopping. */ public void addShutdownHook(Runnable runnable) { shutdownHooks.offer(runnable); } /** * Add an {@link AutoCloseable} into the queue * which will be closed when the service is stopping. */ public void register(AutoCloseable closeable) { closeables.offer(closeable); } }





© 2015 - 2025 Weber Informatics LLC | Privacy Policy