Question

Sorry about the title I can't really figure how to put the question into a title, if anybody can put that better please correct it!

So anyway, in my program I have 2 threads, one is the main program and runs the GUI and everything to do with the user, when it is created it creates a thread which only serves to check a website to see if any updates are available to the SQLite database that the program uses, if there is it pulls the information out in a JSON and must then update the database with an insert query (this is obviously done with syncronized methods surrounding the database's parser in order to ensure that the user isn't accessing data while the database is updated). This is all fine.

However when the program is closed and the main class is terminated the updating thread must also stop as soon as possible, however it may need to stop interacting with the database and close it, as well as interrupting itself. I figure that I need to interupt the thread and close the database if it was opened but how do I make it trigger as soon as the main thread dies? it does not use a loop so I can't check to see if thread1 is alive...

heres the important code so far from the updater:

public static class AutomaticUpdater extends Thread
{
    DictionaryGUI pGUI;
    DatabaseParser pParser;

    public void run()
    {
        Updater pUpdater = new Updater (pParser, pGUI, true); //the manual updater is used to process the data
        for (String sURL : getURLs()) //getURLS() returns areas in the website that contain relevant data
        {
            pUpdater.process(getData(sURL)); //create the INSERT statements and send to database
        }
    }
}

So how do I ensure to death of the Updater when the main thread dies? does a thread killed by the JVM throw off an exception or make any sort of clean up function call that I can override to kill the updater and close the database?

edit: Ok, I have found a solution but I am still willing to accept better ideas...

this is attached to the JFrame of the GUI:

private class ProgramCleaner implements WindowListener
{
    public void windowClosing(WindowEvent e)
    {
        MainLauncher.pAutoUpdater.kill();
    }

    public void windowActivated(WindowEvent e) {}
    public void windowClosed(WindowEvent e) {}
    public void windowDeactivated(WindowEvent e) {}
    public void windowDeiconified(WindowEvent e) {}
    public void windowIconified(WindowEvent e) {}
    public void windowOpened(WindowEvent e) {}
}

where kill interrupts the updater and ensures the database is closed :D

Edit 2: It seems that when the GUI is closed the program almost always gives out a InterruptedException after all the cleaning is done, I proved this with some debug statements and also that the debug file I am sending my errors to doesn't pick it up (ie the program is closed completely) and the exception's stack trace never talks about my code or anything for that matter:

Exception while removing reference: java.lang.InterruptedException
java.lang.InterruptedException
    at java.lang.Object.wait(Native Method)
    at java.lang.ref.ReferenceQueue.remove(Unknown Source)
    at java.lang.ref.ReferenceQueue.remove(Unknown Source)
    at sun.java2d.Disposer.run(Unknown Source)
    at java.lang.Thread.run(Unknown Source)

Does anybody have any idea why this is happening? wait is never actually called inmy code so it has to be something else...

Was it helpful?

Solution

The easiest way would be to make your AutomaticUpdater a deamon thread prior to starting it:

AutomaticUpdater au = new AutomaticUpdater();
au.setDaemon(true);
au.start();

Setting a thread to be a deamon thread means that it will terminate immediately after all user-level threads in your program have terminated. Main is a user-level thread, so if it's the only user-level thread you're running in your program, then this should work. You won't receive any notifications, your updater thread will just die silently (I'm assuming that's what you want).

A second option would be to put a boolean somewhere in your code that tells the updater thread when to stop. You could check that boolean inside your updater's for-loop and have it return immediately when the boolean switches to false.

boolean running = true; //somewhere near the top of your class

...

//main launches the updater thread here

...

//inside updater's run() method:
for (String sURL : getURLs()){
    if(!running) return;
    pUpdater.process(getData(sURL));
}

EDIT

This all assumes that the libraries you are calling for database access do not run their own user-level threads. If they do, then you will need to stop those threads explicitly somewhere in your code for either of these solutions to work.

OTHER TIPS

You should:

  1. Consider using a scheduled executor, or timer, or Quartz, as opposed to rolling your own periodic processor. With a scheduled service you can call shutdownNow, and with a timer task you can call cancel to attempt stopping current and future jobs.

If you decide to stick with you current design then you should:

  1. Design an explicit shutdown method on your updater, and call it from your main thread prior to exiting your app.
  2. Implement Runnable, as opposed to extending Thread
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top