I have a Java application that downloads information (Entities) from our server. I use a Download thread to download the data.
The flow of the download process is as follows:
Log in - The user entity is downloaded
Based on the User Entity, download a 'Community' entities List and Display in drop down
Based on Community drop down selection, Download and show 'Org Tree' in a JTree
Based on Node selection, download Category entities and display in drop down
Based on Category selection, download Sub Category entities and display in drop down
Based on Sub Category selection download a large data set and save it
The download occurs in a thread so the GUI does not 'freeze'. It also allows me to update a Progress Bar.
I need help with managing this process. The main problem is when I download entity data I have to find a way to wait for the thread to finish before attempting to get the entity and move to the next step in the app flow.
So far I have used a modal dialog to control flow. I start the thread, pop up a modal and then dispose of the modal when the thread is finished. The modal/thread are Observer/Observable the thread does a set changed when it is finished and the dialog disposes. Displaying a modal effectively stops the flow of the application so it can wait for the download to finish.
I also tried just moving all the work flow to Observers. All relevant GUI in the process are Observers. Each update method waits for the download to finish and then calls the next piece of GUI which does its own downloading.
So far I found these two methods produce code that is hard to follow. I would like to 'centralize' this work flow so other developers are not pulling out their hair when they try to follow it.
My Question is: Do you have any suggestions/examples where a work flow such as this can be managed in a way that produces code that is easy to follow?
I know 'easy' is a relative term and I know my both my options already work but I would like to get some ideas from other coders while I still have time to change it.
Thank you very much.
You might want to look into using the Future interface.
Stop by http://download.oracle.com/javase/6/docs/api/java/util/concurrent/package-summary.html
It has all you might need to make these tasks easier.
I think the most common method to do this in recent versions of Java is to use SwingWorker:
http://download.oracle.com/javase/6/docs/api/javax/swing/SwingWorker.html
It allows you to fire off background tasks and gives you a convenient done() method that executes on the Swing EDT.
You have to create a "model" for your view, representing the current state of your application. For a tree e.g. it is reasonable to show a "Loading"-node when someone openes a treenode, because else the GUI hangs on opening a node.
If the loading thread finishes loading the node, the "Loading"-node is replaced with the results of the asynchronous action. This makes it easy to open multiple nodes in parallel, because the worker threads all are just responsible for a single child node.
Similar when downloading something: The workers then update a download progress. The downloads-Dialog of Firefox comes to mind here.
Good GUIs aren't easy :).
Related
I have a ArrayList with urls pointing to html files that need to be downloaded and displayed. Right now I'm just looping through the ArrayList and downloading all files on the Main Thread.
After all files have been downloaded, I display the first html page in a jxbrowser. I also made "next" and "prev" buttons so the user can cycle through the html pages.
Currently I need to wait till all Files have been downloaded and sometimes it takes a really long time.
I would like to download all the Files in seperate Threads and to display the first page after it has been downloaded. Other files would continue to download in background. If the user clicks on next button and the Thread downloading that file isn't completed, user should get a an error Message.
I have no clue how to accomplish this as i´m a beginner in java so any help would be appreciated.
Giving an error to a user when they perform a correct action like pressing your Next button is poor interface design.
I suggest creating dummy page content that explains that target URL is loading. Create as many of these pages as you have URLs in your list of downloads. Display those dummy pages to the user initially.
Store the content for those dummy pages in a thread-safe Map implementation, such as ConcurrentHashMap. The key for the map should be the URLs to be downloaded. The values of the map would be the page content. Initially all the values are the dummy page. Then using background threads, you replace each dummy page with the content of a successfully downloaded page.
Use an executor service to perform the downloads. Submit one instance of the downloader for each URL, as the Runnable/Callable task.
As each task completes, put the page content into the map to replace the dummy page.
Then use the JavaFX mechanism to ask the user-interface thread to update its display, transitioning from the dummy page to the downloaded page. Never access or modify the user-interface widgets from a background thread. For more info, search Stack Overflow for posts such as Complex concurrency in JavaFX: using ObservableLists and Properties from multiple worker threads.
Remember to gracefully shut down the executor service. Otherwise its backing pool of threads may continue to run indefinitely like a zombie 🧟♂️.
All of these topics have been addressed many times already on Stack Overflow. So search to learn more.
I am trying to build something, which requires multithreading functionality. The desired work was not done using javascript i.e. Web-Workers.
So I changed focus from javascript to JSP. Now I want to call one method which will execute series of some queries, and at the same time I want to show the affected table rows on other hand. And when first process done with it's execution, I want to stop other process also. My work is done but statically. Now I want to share some resource between this two threads. So that when first thread done with it's execution, I will set some value to that resource(variable,flag), and check that resource in another thread. Is it possible to access variable of one thread in another while it running.
Thanks
JavaScript in a browser is per design not capable of multithreading. You can simulate it a little bit when using setTimeout or setInterval methods.
But, as with the introduction of HTML5, there are now so called WebWorkers available. They run completely separate, spawn a real OS thread, do not have access the DOM but can interact with your UI application e.g. via events.
I'm learning to build gui applications. My current private project is working, the program is doing everything I want. But the implementation looks pretty bad and is not maintainable or extensible anymore. It is not really following MVC or other design pattern in the main parts. So I've started to rework it and would appreciate some advise.
The goal of the program:
It is a monitoring tool getting the data from an external source all the time as long as the application is running. The data is displayed (some labels, text areas, an OSM map) and updated permanently. Depending on the data a button to start the recording of the data (into a file) is enabled or not. When the recording is stopped by the user (same button) some post actions are executed.
Due to lack of knowledge I have implemented two separate SwingWorkers, one to display the current data and one for the recording, started when the button is pressed (is reading the date too!). This is my main pain point. Just one data-retrieving SwingWorker must be sufficent.
So I have started to rework it. I have a gui view class. Once the gui is initialized the SwingWorker (as a gui member variable) is executed and updates the view elements. Fine. Works. But is this a nice approach? The SwingWorker is the central object. From my feeling it should not belong to the view. Other objects should also observe and use its progress. Whenever new data came in gui elements or others should get notified. So I could add several observers to the SwingWorker and call notify(myData) within the doInBackground() method.
My second, bigger issue is concerning the start-stop button to record my data. What kind of implementation approach would you suggest? My idea was to implement a PropertyChangeListener to get the button clicked action. But how can this handle/record the data from the SwingWorker and interrupt on demand? It must get notified permanently too. Or is there some other, better pattern to pulling the data on demand? Is there a nice example with a single SwingWorker and multiple independent listeners/observers?
Thanks in advance,
Niels
I have a GUI and the GUI is starting another thread (Java). This thread is starting a class which is crawling many websites. Now I want to show in the GUI how many websites are crawled and how many are left.
I wonder what's the best solution for that.
First idea was to start a timer in the GUI and periodically ask the crawler how many is left. But I guess this is quite dirty...
Then one could pass the GUI to the crawler and it is calling a GUI method every time the count of ready websites changes. But I don't think that's much better?
What is the best way to do something like that?
It depends.
Ask the crawler how much work it is done isn't a bad idea. The benefit is you can actually control when an update occurs and can balance out the load.
The downside is that the information may go stale very quickly and you may never get accurate results, as by the time you've read the values, the crawler may have already changed them.
You could have the crawler provide a call back interface, which the GUI registers to and when the crawler updates it's states, calls back to the GUI.
The problem here is the UI may become swamped with results, causing to lag as it tries to keep up. Equally, while the crawler is firing these notifications, it isn't doing it's work...
(Assuming Swing)
In either case, you need to make sure that any ideas you make to the UI are made from within the Event Dispatching Thread. This means if you use the callback method, the updates coming back will come from the crawlers thread context. You will need to resync these with the EDT.
In this case you could simply use a SwingWorker which provides mechanisms for syncing updates back to the EDT for you.
Check out Concurrency in Swing for more details
register a callback function to your thread. when your data is dirty, invoke this callback function to notify GUI thread to update. don't forget to use synchronization.
I have a SWING UI that contains a button that creates a new SwingWorker thread. That thread then queries the SQLite database for results to put them in a JTable. In my StringWorker constructor, the parameters are various fields taken from other SWING components such as a JSpinner, JComboBoxes, etc.
Since I'm new to all of this thread thing, I'd like some advice from more knowledgeable programmers on how I should go about doing what I want to do.
I'd like to know if threads automatically end when I close the program with System.exit(0); so I don't end up with memory leaks
What is the best way to make sure I don't have two threads accessing my database at the same time (let's say the user clicks multiple times on the button or, other case, an administrator is updating the database with some files as input (within my program), then while the first thread is parsing the files and updating the database, he wants to query the database using the button, etc.).
Is it slower to use threads? At first I did all my calculations right in the EDT and of course the UI locked every time after pressing the button, but it only locked for about 5 seconds if I recall correctly. Now, when I press the button, it doesn't lock up but it seems like the result take about a little bit less than twice as long to show up in the JTable. Is it because I made a mistake in my code or is this normal?
I though about using a static field in the class the queries are in and setting it to true if it's in use. Is that the correct way of doing it? That way, not matter which thread is using the database, the second thread won't launch.
If it's not absolutely necessary (it shouldn't be), don't use System#exit in your code. Here are some explanations why and what is better.
Your database is capable of handling two concurrent requests, so it's not a bad thing in itself. If you use JDBC and its pooled connections via DataSource, then you should probably restrict the usage of one such a connection to one thread at a time. To cure the problem of having redundant database queries, e.g. when "clicking twice", there is probably more than one solution. I assume here that you mean the scenario where you have a Swing UI that is distributed to several people, and each of these instances talks to the same database -> simply disable your button as long as the execution of the database query takes.
It's slightly slower if you do not run your code directly in the Event Dispatch Thread due to scheduling of execution of your workers, but this should not be noticable. To see what goes wrong I would have to see the relevant code.
I'd like to know if threads automatically end when I close the program with System.exit(0);
Yes. Entire process will end and threads that are part of this process. However, if you don't call System.exit(), all non daemon threads must finish before process is gone.
What is the best way to make sure I don't have two threads accessing my database at the same time
Since it's a Swing application, I assume that both you and administrator can't access the application at the same time. However, to guarantee that even in single application you can't start more than one operation affecting database, you have to block UI. Either disable buttons or put glass pane on top of UI. Modal progress dialog is also helpful.
Is it slower to use threads?
No, it is not slower if done right. Slow operation will take as long as it takes. You can't fix it with threads, but you can, either keep speed (perceived) the same while providing nice, non blocking UI or you can do more than one slow operation at a time and therefore increase that perceived speed.