How to silently termintate a Java program with threads and locks - java

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) {
}
}
}
}
}

Related

Shutdown a java app (multiple threads) gracefully

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.

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 restart thread without using Thread.stop()?

I have a client-server application that runs the receive method to run in a separate thread. Thread is given some time to finish the job and the thread will be checked for the status.
There are occasions when the receive method will be blocked due to packet or ACK loss. If that happens, how can I stop the thread and start it again the next attempt?
As we all know, Thread.stop() is deprecated.
You can't restart a Java thread at all, with or without Thread.stop().
You have to create a new one.
You can however reuse a Runnable.
You can use interrupts to send to the thread and handle them to do a retry. Here is a sample that will start a thread that will not quit until the boolean done is set. However i'm interrupting the thread from a main thread to make it start over.
public class Runner implements Runnable {
private boolean done;
#Override
public void run() {
while (!done) {
try {
doSomeLongRunningStuff();
} catch (InterruptedException e) {
System.out.println("Interrupted..");
}
}
}
private void doSomeLongRunningStuff() throws InterruptedException {
System.out.println("Starting ... ");
Thread.sleep(300);
System.out.println("Still going ... ");
Thread.sleep(300);
done = true;
System.out.println("Done");
}
public static void main(final String[] args) throws InterruptedException {
final Thread t = new Thread(new Runner());
t.start();
Thread.sleep(500);
t.interrupt();
Thread.sleep(500);
t.interrupt();
}
}
Whether you can do it this way or not depends on what you are calling. Your framework doing the TCP connection may or may not support interrupting.
We should not restart a thread which is not valid , once thread has comepleted its execution.

Java equivalent of .NET's Environment.HasShutdownStarted

In .NET, you can check the Environment.HasShutdownStarted property to see whether your service is being unloaded for whatever reason, and perform graceful unloading/cleanup.
So instead of:
while (true) { }
...you can use...
while (!Environment.HasShutdownStarted) { }
Is there an equivalent thing in Java?
Perhaps you're looking for a shutdown hook? This allows you to specify a thread to be run when the application is closed (as long as it's not brutally forced closed with kill -9 or similar, but in that case no environment can guarantee to do anything on shutdown.)
Runtime.getRuntime().addShutdownHook(new Thread() {
public void run() {
//Code here.
}
});
From a practical perspective, you should also make these threads quick to execute - since otherwise the application will appear to hang upon exiting, and no-one likes that (plus, the OS or user may choose to kill off the application, aborting the hook at an arbitrary point.)
You can add multiple shutdown hooks, and they will be executed concurrently (and in an arbitrary order.)
Removal of shutdown hooks can be down in a similar way by calling removeShutdownHook().
You could add a shutdown hook. Basically registers an unstarted thread that will run when the application terminates.
Runtime.getRuntime().addShutdownHook(new Thread() {
public void run() {
// logic for making a clean shutdown...
}
})
The link above has a very good description of what happens during shutdown.
You can look at the shutdown hook API, and instead of doing
while(true) {
}
You can declare a member in your thread/runnable implementation to signify shutdown:
class MyRunnable implements Runnable {
private running= false;
public void setRunning(boolean running) {
running= running;
}
public void run() {
setRunning(true);
while(running) {
// do task
}
}
}
public static void main(String[] args) {
final MyRunnable myRunnable= new MyRunnable();
final Thread runThread= new Thread(myRunnable);
Runtime.getRuntime().addShutdownHook(new Thread() {
public void run() {
myRunnable.setRunning(false);
}
});
runThread.start();
runThread.join();
}
This is not a perfect solution, but should get you at least in the right direction.

Java Shutdown hook not run

I am new to Java/threads and I inherited something like the following code. It is a command line program that main() only starts 5-6 different kind of threads and exits with ^C. I want to add a shutdown hook to close all threads properly and adapted it the following way.
I added a Shutdown hook and a stopThread() method in all threads (like the one in MyWorker class)
The problem is that when I press ^C I don't see the end message from the Thread's run method. Is this done in the background or is there something wrong with my method. Also, Is there a better pattern I should follow?
Thanks
public class Main {
public static MyWorker worker1 = new MyWorker();
// .. various other threads here
public static void startThreads() {
worker1.start();
// .. start other threads
}
public static void stopThreads() {
worker1.stopThread();
// .. stop other threads
}
public static void main(String[] args)
throws Exception {
startThreads();
// TODO this needs more work (later)
Runtime.getRuntime().addShutdownHook(new Thread() {
#Override
public void run() {
try {
stopThreads();
} catch (Exception exp) {
}
}
});
} }
public class MyWorker extends Thread {
private volatile boolean stop = false;
public void stopThread() {
stop = true;
}
public void run() {
while (!stop) {
// Do stuff here
}
// Print exit message with logger
}
}
Shutdown Hooks may not be executed in some cases!
First thing to keep in mind is that it is not guaranteed that shutdown hooks will always run. If the JVM crashes due to some internal error, then it might crash down without having a chance to execute a single instruction.
Also, if the O/S gives a SIGKILL (http://en.wikipedia.org/wiki/SIGKILL) signal (kill -9 in Unix/Linux) or TerminateProcess (Windows), then the application is required to terminate immediately without doing even waiting for any cleanup activities. In addition to the above, it is also possible to terminate the JVM without allowing the shutdown hooks to run by calling Runime.halt() method.
Shutdown hooks are called when the application terminates normally (when all threads finish, or when System.exit(0) is called). Also, when the JVM is shutting down due to external causes such as user requesting a termination (Ctrl+C), a SIGTERM being issued by O/S (normal kill command, without -9), or when the operating system is shutting down.
When you call System.exit() or terminate via a signal, it stop all the existing threads and starts all the shutdown hooks. i.e. all your threads could be dead by the time you hook starts.
Instead of trying to stop threads cleanly, you should ensure resources are closed cleanly.
I guess you can shift your code to ExecutorService
private final ExecutorService pool;
pool = Executors.newFixedThreadPool(poolSize);
pool.execute(Instance of Runnable);
pool.shutdown();
ExecutorService.shutdown
Initiates an orderly shutdown in which previously submitted tasks are executed, but no new tasks will be accepted. Invocation has no additional effect if already shut down.
Try making your threads as daemon threads.
Add a constructor
public MyWorker(boolean isDaemon) {
this.setDaemon(true);
}
or set to daemon before calling start.
worker1.setDaemon(true);
worker1.start();
When you press Ctrl C and exit, the threads will be stopped.
What is happening here is that you invoke the stopThread() method, but you don't wait the the threads are actually finished before terminating.
If you invoke a join() on all threads before stoping the JVM, you will probably see your 'stop logs'.
public static void stopThreads() {
worker1.stopThread();
// .. stop other threads
for(Thread t: workers) {
t.join();
}
}

Categories

Resources