Shutdown a java app (multiple threads) gracefully - java

I am trying to set up a shutdown hook to handle SIGTERM (kill -15). It shuts down but doesn't look like it gracefully finish up ** processing** function as it never output the log "Thread has been shutdown".
public class Runner {
public static void main(String[] args) {
Test test = new Test();
Runtime.getRuntime().addShutdownHook(new Thread() {
#Override
public void run() {
try {
logger.warn("Shutting things down..."); // This works
test.stop();
} catch (Exception ex) {
logger.error("Error shutting the app gracefully", ex);
}
}
});
test.processing();
}
}
public class Test {
private volatile boolean processingExit = false;
public void stop() {
processingExit = true;
}
public void processing() {
while (!processingExit) {
//do work here
logger.info("doing work... keep printing..."); //This works until I send a kill -15 signal
}
// This log never works
logger.info("Thread has been shutdown"); // This doesn't works
}
}

The problem is that as soon as the shutdown hook thread completes, the process is halted, you need to have the shutdown hook thread wait for the main thread.
Copied from https://stackoverflow.com/a/2922031/1544715
From the docs:
When the virtual machine begins its shutdown sequence it will start all registered shutdown hooks in some unspecified order and let them run concurrently. When all the hooks have finished it will then run all uninvoked finalizers if finalization-on-exit has been enabled. Finally, the virtual machine will halt.

Related

Stopping a running process via GUI, in java

I have a GUI program that executes TestNG automation scripts. It's meant for users to easily configure some setting and launch the automation script that they want.
One thing I need to add is the ability to instantly stop the running TestNG process. Something like how in Eclipse, the 'Terminate' button will instantly stop whatever is running.
This is what the code that launches the TestNG tests looks like:
public class ScriptRunner implements Runnable {
public void runScript() {
Thread testRun = new Thread(this);
testRun.start();
}
#Override
public void run() {
//various other things are configured for this,
//but they're not relevant so I left them out
TestNG tng = new TestNG();
//While this runs, various browser windows are open,
//and it could take several minutes for it all to finish
tng.run();
}
}
As per the comment, the tng.run() can take several minutes to complete, and it's performing several things, opening/closing browser windows, etc.
How can I just instantly terminate the process, like you would when running an application from an IDE?
EDIT:
Per the comments, I'm attempting to use a ServiceExecutor and shutDownNow() The code is looking like this:
ExecutorService executorService = Executors.newFixedThreadPool(10);
public void runScript() {
executorService.execute(this);
}
//this method gets called when I click the "stop" button
public void stopRun() {
executorService.shutdownNow();
}
#Override
public void run() {
//same stuff as from earlier code
}
Spawn a child JVM process using ProcessBuilder or Runtime and you will be able to terminate that process when the user requests that the script stops running.
You can use ExecutorService to start test execution into one another thread. You can choose to have many thread in parrallel or juste one thread for all tests in sequence by choosing which executor service you need.
After that, start the execution of all tests in the same executor service instance by calling submit() method on it. You can stop the execution of all submitted runnables by calling shutdownNow() method.
It is important to use the same instance of ExecutorService, otherwise you start each test in a different thread and you will not enable to break the execution chain (or by calling shutdownNow() on all of them).
I was recently working on the executor framework. Here I have listed my problem
http://programtalk.com/java/executorservice-not-shutting-down/
Be careful if you are doing some IO operations the executor service may not shutdown immediately. If you see the below code stopThread is important because it tells your program that the thread has been asked to stop. And you can stop some iteration what you are doing.
I will modify your code like this:
public class MyClass {
private ExecutorService executorService;
private boolean stopThread = false;
public void start() {
// gives name to threads
BasicThreadFactory factory = new BasicThreadFactory.Builder()
.namingPattern("thread-%d").build();
executorService = Executors.newSingleThreadExecutor(factory);
executorService.execute(new Runnable() {
#Override
public void run() {
try {
doTask();
} catch (Exception e) {
logger.error("indexing failed", e);
}
}
});
executorService.shutdown();
}
private void doTask() {
logger.info("start reindexing of my objects");
List<MyObjects> listOfMyObjects = new MyClass().getMyObjects();
for (MyObjects myObject : listOfMyObjects) {
if(stopThread){ // this is important to stop further indexing
return;
}
DbObject dbObjects = getDataFromDB();
// do some task
}
}
public void stop() {
this.stopThread = true;
if(executorService != null){
try {
// wait 1 second for closing all threads
executorService.awaitTermination(1, TimeUnit.SECONDS);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
}
}
}
What about this,
add a volatile static boolean and make the thread code look like...
if(ScriptRunner.runThread){
//Do some stuff here
}
if(ScriptRunner.runThread){
//Do some other stuff here
}
if(ScriptRunner.runThread){
//Do some other stuff here
}
if(ScriptRunner.runThread){
//Do rest of the stuff here
}
Now you can add a button in your main GUI that simply sets the runThread to false so the thread will terminate nearly instant leaving all the leftover code untouched as you press the Stop button.
public class ScriptRunner implements Runnable {
volatile static Boolean runThread = true;
public void runScript() {
Thread testRun = new Thread(this);
testRun.start();
}
public void terminate(){
runThread = false;
}
#Override
public void run() {
//various other things are configured for this,
//but they're not relevant so I left them out
TestNG tng = new TestNG();
//While this runs, various browser windows are open,
//and it could take several minutes for it all to finish
tng.run();
}
}
How about a new Thread? You have to add an private Thread thread; in the gui and when ever you start
thread = new thread(){
#Override
public void run(){
//start process here
}
};
thread.start();
and to stop "terminate"
thread.stop();(depracted) or thread.setDeamon(true);
Everytime I have to stop a process by the gui I use this.
Hope I could help ;)
In your GUI somewhere you have something like
ScriptRunner scriptRunner = new ScriptRunner();
scriptRunner.runScript();
When you want to stop it call
scriptRunner.interrupt();
Change the code in ScriptRunner
private Thread testRun;
public void runScript() {
testRun = new Thread(this);
testRun.start();
}
public void interrupt() {
testRun.interrupt();
}
Save all created processes and kill them when your program ends:
public class ProcessFactory {
private static Set<Process> processes = new HashSet<>();
private static boolean isRunning = true;
public static synchronized Process createProcess(...) throws ... {
if (!isRunning)
throw ...
... // create your spawned process
processes.add(process);
return process;
}
public static synchronized void killAll() {
isRunning = false;
for (Process p : processes)
p.destroy();
processes.clear();
}
public static void registerShutdownHook() {
Runtime.getRuntime().addShutdownHook(new Thread() {
void run() {
killAll();
}
});
}
}
This can be improved by adding a mechanism that removes already dead processes, but you get the general idea.

How to silently termintate a Java program with threads and locks

In C programs using system threads for example, I can pass a SIGINT with Ctrl+C and the process will be killed silently. But when I do the same thing to a Java program with threads, locks, semaphores et cetera, the JVM just stops there and I have to kill the process "outside", by closing the terminal or rebooting the system. How can a make a Java program silently exit as it should without closing the terminal when I see some wrong behaviors in runtime?
You can add a shutdown hook to the JVM that gets triggered when a SIGINT is received and then in there call Runtime.getRuntime().halt(0). That will kill the process. You can even use the Shutdown Hook to clean your running Threads.
[EDIT] My initial answer was to use System.exit() in the hook. But that will not work because System.exit will trigger the already running hook.
You can try this example with the hook and not registering the hook.
public class Exit {
public static void main(String[] args) {
Runtime.getRuntime().addShutdownHook(new ExitHok());
Thread t = new Thread(new Printer());
t.start();
}
private static class ExitHok extends Thread {
#Override
public void run() {
System.out.println("Received shutdown");
Runtime.getRuntime().halt(0);
}
}
private static class Printer implements Runnable {
#Override
public void run() {
int counter = 0;
while (true) {
System.out.println(++counter);
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
}
}
}
}
}

How to gracefully stop Guava AbstractScheduledService using a shutdown hook?

I am using an AbstractScheduledService with a scheduler. A simple pattern like:
class MyService extends AbstractScheduledService {
// KEEP THIS VAR IN MIND W.R.T the SHUTDOWN_HOOK BELOW
public static volatile boolean keepRunning = true;
protected void startUp() throws Exception {
// startup stuff
}
protected void runOneIteration() throws Exception {
// main logic stuff
}
protected void shutDown() throws Exception {
// shutdown stuff
}
protected Scheduler scheduler() {
return Scheduler.newFixedRateSchedule(0, 1, TimeUnit.SECONDS);
}
}
Now, I want to implement a typical shutdown hook like this: (the below snippet will be in main method)
final Thread mainThread = Thread.currentThread();
LOGGER.debug("Adding the shutdown hook");
Runtime.getRuntime().addShutdownHook(new Thread() {
#Override
public void run() {
keepRunning = false;
LOGGER.debug("The shutdown hook was engaged. Setting keepRunnning to false.");
try {
// Is this appropriate?
mainThread.join();
} catch (InterruptedException e) {
// handle exception here
}
}
});
The shutdown hook is from typical docs example. It doesn't seem to work well with the Guava services pattern since the service itself is running on a different thread.
My service has a polling loop in the runOneIteration() logic. I want it to complete it's current task at hand and then shutdown gracefully when is sees that the keepRunning is now false since the Shutdown hook was engaged some time in the recent past when it was busy with its current iteration.
Any ideas how this can be done gracefully (complete current iteration and then shutdown)?
Wouldn't you just call stopAndWait()?
Runtime.getRuntime().addShutdownHook(new Thread() {
#Override
public void run() {
service.stopAsync().awaitTerminated(60, TimeUnit.SECONDS);
}
});

Application not terminated after all code executed

I'm about to learn the java threading facility.
I have 2 classes:
public class Main {
public static void main(String[] arg) throws Exception {
Timer timer = new Timer();
timer.schedule(new ExecuteTimer(Thread.currentThread()), 2000);
try {
Thread.currentThread().join();
} catch (InterruptedException ex) {
System.out.println("timer stopped");
}
System.out.println("try block executed");
}
}
and the timer class:
public class ExecuteTimer extends TimerTask {
public ExecuteTimer(Thread thread) {
creatingThread = thread;
}
private Thread creatingThread;
#Override
public void run() {
System.out.println("I'm executed!");
creatingThread.interrupt();
}
}
When I debug the code. I have following output:
I'm executed!
timer stopped
try block executed
Everything seems to be final except the app didn't exit after I have the output above. The eclipse remain in debug mode and no exception has been thrown.
After you no longer need the Timer to run tasks, you should call timer.cancel() to release its thread.
Use thread.setDaemon(true) to tell the JVM to make the thread a daemon thread. Daemon threads do not prevent the program from exiting.

Invoke a cleanup method for java user thread, when JVM stops the thread

I have J2SE application running in linux. I have stop application script in which i am doing kill of the J2SE pid. This J2SE application has 6 infinitely running user threads,which will be polling for some specific records in backend DB.
When this java pid is killed, I need to perform some cleanup operations for each of the long running thread, like connecting to DB and set status of some transactions which are in-progress to empty.
Is there a way to write a method in each of the thread, which will be called when the thread is going to be stopped, by JVM.
You can always try to implement a shut down hook using Runtime.addShutDownHook, or encapsulate the long-running-code in a try and the cleanup in finally.
A minimal example doing roughly what you want to do (but for a single worker thread for simplicity).
public class Test extends Thread {
static volatile boolean keepRunning = true;
public static void main(String[] args) throws InterruptedException {
final Thread t = new Test();
t.start();
Runtime.getRuntime().addShutdownHook(new Thread() {
public void run() {
System.out.println("Shutting down...");
keepRunning = false;
t.interrupt();
try {
t.join();
} catch (InterruptedException e) {
}
}
});
}
public void run() {
while (keepRunning) {
System.out.println("worknig...");
try {
sleep(1000);
} catch (InterruptedException e) {
}
}
System.out.println("cleaning up.");
}
}
Output when interrupting with Ctrl-C:
worknig...
worknig...
worknig...
^CShutting down...
cleaning up.
Output when killing with kill pid
worknig...
worknig...
worknig...
worknig...
Shutting down...
cleaning up.
Output when killing with kill -9 pid
worknig...
worknig...
worknig...
worknig...
worknig...
Killed
(No cleanup executed.)

Categories

Resources