Controlling the closure of a programFrom WikiJavabuy this book
This technique solves your problems when for example your program abruptly exits because of an exception and you want to save the data already calculated, so you can restart your program and just continue, instead of starting again from a scratch.
The problemAll java programs are run within the Java Virtual Machine. That can be seen as a sort of container for the java programs, the flow is generally that when you run your program in the JVM, you first start the JVM, who then takes care about loading your program running it. In normal cases the JVM waits for the end of your program and then ends itself. It can happen, though, that the JVM ends when your program does not expect it. For example the user forcibly closed the execution (maybe by hitting on ctrl+c) or an uncaught exception forced your whole process to end. Such cases are a bit tricky, because if the JVM exits, then your program will just stop being executed, whatever it was doing at the moment it was stopped. In this situation not even the finally blocks will be run. simply your program will stop working, whatever was done was done... the JVM will release all the locks. The solutionFortunately we have a way to intercept the closing of the JVM. Using the method: public void addShutdownHook(Thread thread) from the We can specify a runnable Thread class that will be run just before the JVM will start closing. By simply writing: Runtime.getRuntime().addShutdownHook(new OnShuttingDown()); Where private class OnShuttingDown extends Thread { public void run() { closeProgram(); } } We can control the closing of our program in any case. The run method of It is possible also to remove the shutting down hook by using the method: public void removeShutdownHook(Thread thread) Using these two methods you are able to fully control the exiting of the JVM in some parts of your program. Note, the thread added in the hook will be called in any case when the JVM will stop. Including the normal termination of your program. This means that this technique can substitute any other mechanism to control the closure of the program. in particular, if your program terminates correctly, its full code will be executed, and the ShutdownHook will be run as well after it. Explanation of the example programThe program below saves the timestamps in a text file. Without using the By adding the In the following example:
I recommend you to execute the example below in a command shell and try letting it reach it's natural end or forcing its end by hitting Ctrl+c, to compare the results. the whole codepackage org.wikijava.basic.safeFileWriter; import java.io.BufferedWriter; public class SafeFileWriter { private BufferedWriter outputStream; private OnShuttingDown onShuttingDown; private class OnShuttingDown extends Thread { private SafeFileWriter safeFileWriter; public void run() { System.out.println("finish caught. closing"); this.safeFileWriter.finish(); System.out.println("closed"); } public void setSafeFileWriter(SafeFileWriter safeFileWriter) { this.safeFileWriter = safeFileWriter; } } public void run() throws InterruptedException { try { int i = 0; while (i++ < 5) { try { Long data = new Date().getTime(); this.outputStream.write(data + "\n"); System.out.println("written: " + data); Thread.sleep(1000); } catch (IOException e) { e.printStackTrace(); } } } finally { System.out.println("runnning finally"); } } public static void main(String[] args) throws IOException, InterruptedException { if (args.length != 1) { System.err.println("Usage: \n SafeFileWriter filename"); return; } SafeFileWriter program = new SafeFileWriter(); program.init(args); program.run(); System.out.println("exiting main"); } public void finish() { System.out.print("saving file and releasing resources .... "); try { this.outputStream.flush(); } catch (IOException e) { e.printStackTrace(); } finally { try { this.outputStream.close(); } catch (IOException e) { e.printStackTrace(); } } System.out.println("Done"); } private void init(String[] args) throws IOException { this.outputStream = new BufferedWriter(new FileWriter(args[0])); this.onShuttingDown = new OnShuttingDown(); this.onShuttingDown.setSafeFileWriter(this); Runtime.getRuntime().addShutdownHook(this.onShuttingDown); } }
|
