Java - Destroying objects that are in the process of doing something
I've had a look at the posts about destructors in Java and have learnt that Java does not have them but I am confused about what I need to do in my application if there is no such thing as a destructor.
My application allows a user to create a series of webcrawlers, which are held in an arraylist. Each Crawler has a progress panel gui showing pages crawled etc and enables the user to pause that crawler. However, the user might also want to "terminate" that crawler. It should be noted that each instan开发者_高级运维ce of the Crawler class has an instance of a Scraper class, which in turn has an instance of a DatabaseConnection class.
What do I need to do to enable the user to press "Terminate" and for that Crawler, and its Scraper, and the Scraper's DatabaseConnection, all to be "shut down" and removed from the system.
Any advice would be appreciated.
First of all you need for this to run on separate threads to work well (anything you see about Java GUI's being unresponsive is because this is not heeded).
The trick then is to have the thread(s) doing things, regularly check that a given condition is still true, and let your cancel button go in and reset the condition so it is false (like setting a field, or calling a setKeepGoing(false) metod). When the threads then find out they have been asked to stop, they stop and clean up accordingly.
The garbage collector of the JVM will eventually delete from memory any object to which there is no more reference. The easiset way to delete the object is to delete the reference to it with a call to arrayList.remove(elementid)
I would say: "Ask nicely to stop".
Thread.stop was deprecated from the API because it allowed you to stop things mid-flight, leaving applications in a potential inconsistent state. In your particular case, garbage collection cannot be relied upon to clean up DB connections left open, so you need to manage that in your logic.
First, I agree with the other answers in that your app needs layering between the user interface and the actual processing -crawling in your case-. As you explain, the crawlers will typically be long running tasks. Therefore they will need to live in their own execution thread, be it in a dedicated Thread
or even better using a [ExecutorService][1]
.
Then, you have different ways to stop your long-running tasks: You could use thread Interruption to signal that a given thread and its related execution should stop service or, you can use some app-level logic to send a poison-pill to the task. With the ExecutorService
, you can hold on to the [Future][4]
s returned by the service and use them to request a cancel of your task.
In your interruption logic, remember to clean up after resources like Files and DB connections.
Have a read on java concurrency here: http://download.oracle.com/javase/tutorial/essential/concurrency/index.html
Each crawler will be its own Runnable that performs its task. When you give the crawler a terminate command you can implement some code in the crawler that will deallocate the resources (database connections etc.) and cease execution. If you are using the executor framework, you can also use the Future that is provided upon scheduling the Executor and call 'shutdown' when you're done to ensure the Thread is cleaned up.
精彩评论