I'm trying to clean up resources in my application before it shuts down, following on from my previous question (Detecting When A Java Application Closes) I have implemented the following code which performs the cleanup operation perfectly.
//Intercept when the application closes
Runtime.getRuntime().addShutdownHook(new Thread()
{
#Override
public void run()
{
//Reclaim resources from MIDI usage
if(_midiInstance.CleanUp())
{
Logger.Add("Closed resources successfully on ShutDown");
}
else
{
Logger.Add("Failed to close all resources on ShutDown");
}
System.exit(0);
}
});
Although the System.exit(0); call is understood and processed the application continues to run, just without a visiable GUI. I've thought about placing the System.exit(0) call just outside of the Thread but then it's out of scope, there aren't any other threads or streams running.
Is there an additional step I need to take when hooking in to the ShutDown event to ensure everything closes?
Thanks for your time, I greatly appreciate it.
After reading your other question, it seems like your are probably not calling dispose() on your window(s). If true, that would explain the cause of your problem.
You need to over ride the windows close button:
//overriding the windowClosing() method will allow the user to click the close button
addWindowListener(
new WindowAdapter()
{
public void windowClosing(WindowEvent e)
{
System.exit(0);
}
});
By doing this the program will close not just become invisible.
Related
In Netbeans, my program won't exit after I customise the windowClosingEvent.
I add the database connection closing instructions into the windowClosingEvent method to make sure that my database connection can be disconnected if user close the window instead of clicking disconnecting database button.
Then I manually add "system.exit(0);" within the closingEvent method generated by Netbeans. Now my program can finish. But I can't understand why it can't finish by itself if I add the windowClosing Event without explicitly turning off the program.
If you are using WindowListener interface or a WindowAdapter and you look at the original implementation in their windowCloseing(e) method, you will realise they did nothing for the implementation:
//Invoked when a window is in the process of being closed. The close
//operation can be overridden at this point.
public void windowClosing(WindowEvent e) {}
Hence when you use it, you have to explicitly tell them what to do when you close the window. If don't override it, nothing will happen. If you do not have anything special to do other than terminating the program on closing the window, usually we write System.exit(0); in the overridden windowClosing() method.
Example:
frame.addWindowListener(new WindowAdapter() {
#Override
public void windowClosing(WindowEvent e) {
System.exit(0);
}
});
For your case, instead of just writing System.exit(0), you may want to check whether the database connection is already closed:
#Override
public void windowClosing(WindowEvent e) {
//Check if database connection is closed
//Close DB connection if open
System.exit(0);
}
Because closing the window doesn't mean that the program should be terminated. You should do in explicitly or you can configure you window to terminate program on window closing. frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
I currently have the following problem:
I have made a 'Cache Updater Thread', which checks for updates and then sleeps for some amount of time. I have also build a Button, which enables the user to check for updates manually. The Thread is built like this:
public static Thread cacheUpdater = new Thread(new Runnable() {
int milliSecondSleepTime = 10000;
public void run() {
try {
cacheUpdater.setPriority(Thread.MIN_PRIORITY);
//Infinite loop
while (!terminate) {
syncStatus.set(0);
//Check for updates with some methods, not important here.
syncStatus.set(1);
Thread.sleep(this.milliSecondSleepTime);
}
}
catch (InterruptedException e) {
//First check if it is termination time
if (!terminate) {
syncStatus.set(0);
this.run();
}
}
catch (Exception e) {
System.out.println(e);
}
return;
}
});
If the user clicks the manual-update button, the following code is being runned:
#FXML public void syncOnRequest() {
//Only call interrupt, because then it will start again when terminate is still false
CacheManager.cacheUpdater.interrupt();
System.out.println(CacheManager.cacheUpdater.getState().equals(State.TIMED_WAITING));
while (!CacheManager.cacheUpdater.getState().equals(State.TIMED_WAITING)) {
//LOOP FOREVER
}
//Some code that needs to be executed after the cache is updated
}
I would like to continue executing code in the syncOnRequest() method, when the cache updater is ready with its manual update. I had the idea to check if it is sleeping, but this is not working, because the System.out.println() immediately returns true. I have measured the time it takes to do the update, and its between 200 and 400 ms.
What am I doing wrong here? And why is it always returning true?
Additional question: sometimes a click on the button just kills the Thread, because it just woke up. The InterruptedException is not thrown.
How can I make sure the Thread will also restart in that case?
Note that Thread#interrupt() is the only polite way to ask your thread to interrupt itself (unless you explicitly implement another). Using it to restart the check is therefore a bad practice. So is checking the thread state for synchronization purposes and exposing the thread that keeps your cache up-to-date to external clients.
You manager should have a updateCache() method you will call directly from UI code and auto-update thread will call the same method periodically*. In that method, make sure that access to your cached data is either correctly synchronized or it happens atomically.
*) Instead of implementing your own periodic thread, consider using
Timer and TimerTask classes as well as making it a daemon thread.
In my app I got some activities and a ReceiverThread.class.
The Thread is started from two different activities. And everytime I switch to another Activity and recall the former active Activity it starts a new Thread. So if I do some test on my app for about 10 Minutes or the app is simply used for some time, there is a mass of Threads open and all do the same.
Most of the time the Threads are on TimedWait.
This gives me wrong data and causes the app to lag hard, sometimes its not even responding.
Is there a good possibility to stop a thread onPause() or onStop() ? Because many of the methods are deprecated. Or how to resume a previous started Thread and so prevent the Activity from creating a new one?
This is my ReceiverThread.run():
public void run() {
initiateCAN();
while (true) {
try {
Thread.sleep(60);
mHandler.post(r);
} catch (InterruptedException e) {
break;
}
}
}
If something is not clear or missing, please feel free to ask and I will edit my post, but don't just simply downvote.
The recommended way to do this is to use the built-in interrupt system. You can then stop the thread by calling Thread.interrupt() (best in onPause() if you don't want multiple instances). Your run method would need to be somewhat changed:
public void run() {
initiateCAN();
try {
while (!isInterrupted()) {
Thread.sleep(60);
mHandler.post(r);
}
} catch (InterruptedException e) {
}
}
While this might work, it's still better to use a Service or another way to make sure there is only one instance at one time (maybe fragments instead of activities?).
You can use Android Services, and that service starts the thread. When you switch the activity, the services is running and not is necessary start a new thread.
Within the main() of my application I have the following code to back up data so it doesn't get lost in the event of a system shut down.
//add hook to trigger Production Shutdown sequence
Runtime.getRuntime().addShutdownHook(new Thread(new Runnable() {
public void run() {
Production.shutdown();
}
}));
However, whether I press the Stop button in my IDE or rely on input via the log (code shown below) it never seems to save data to the database or write any logs to the console.
ctx.deploy(server);
server.start();
//start the production process
Production.init();
System.in.read();
server.stop();
How come this shutdown function is not being executed?
You need to use the Exit button, not Stop, see my answer here for more details.
Note that this feature is currently available only in Run mode, not in Debug.
System.exit(0)
add this line in your code. Debug from here onwards
Surprisingly terminating a midlet doesn't work in my application. Maybe it is because I'm using Threads, but destroyApp() and notifyDestroyed() are not sufficient.
Take for example the following code:
protected void destroyApp(boolean arg0) throws MIDletStateChangeException {
System.out.println("destroying");
notifyDestroyed();
}
protected void startApp() throws MIDletStateChangeException {
try {
// init modules
controller.initialize();
}catch (Exception e) {
viewer.showAlert("error in startApp() init controller");
destroyApp(true);
}
}
You are specifically calling notifyDestroyed() from inside startApp().
My best guess is that the handset (or emulator) you are trying this on doesn't handle it too well.
Try this instead:
When controller.initialize() throws an exception, display a simple Form with a single "Exit" Command and a StringItem error message.
Call notifyDestroyed() from a CommandListener.commandAction() callback.
As far as threads are concerned, it is up to you to have them nicely terminate when the user wants to exit your application.
Most MIDP runtimes will be able to deal with some threads not terminating nicely but leaving system resources not properly cleaned may cause problems, especially on platforms that try to never terminate the Java Virtual Machine process itself.
you should call 'notifyDestroyed' method to exit your application not 'destroyApp' method.