I'm looking for suggestions for a framework GUI with computationally intensive threads. Practically, the GUI should have a button that starts one manager thread. That manager thread will start a number (about 20 to 40) of worker threads that are computationally intensive and each thread runs for about an hour. The worker threads should report progress / messages back to the manager thread. The manager thread should report messages back to the gui, ie JTextArea, that describe the worker thread configuration, status, progress, and final results. Also, the manager thread should accumulate and rank the results for display in the GUI.
When I write this definiation down, I think, I can use invoklater to start the swing thread. When a button is started, start a manager thread. The manager thread determines the number of cpus, sets up an executor service, and starts running the worker threads.
But, how do the worker threads communicate back to the manager thread in a thread safe manner, and also, how does the manager thread communicate back with the swing elements.
I have been playing with a MVC formulation, but I'm thinking an publisher / subscriber system makes more sense, since there are only messages going one way.
Oh, but I fogot, need to be able to press cancel to stop the whole thing in a safe manner, ideally with worker threads writing their progress to a file so they don't have to start over from scratch.
And, if the above isn't enough question, how do I write unit tests for the various components .... Can I be a "good programmer", and start by writing the unit test first?
The SwingWorker class caters to all your requirements. It runs in the background, can report progress, is cancellable and can provide intermediate results. And, of course, does it in a thread-safe manner. You'll need just to provide your own solution to make the tasks restartable. Check out the SwingWorker tutorial, it is all covered there.
Joined: Sep 26, 2010
Thank you for the suggestion on the tutorial. It does covers getting interim results and canceling. But, can SwingWorker limit the amount of threads running? Or, how would I limit the threads. I have on the order of 20 threads that I would like to run, limited to the number of CPUs, so it doesn't slow down the system.
The baseline flip code, from SwingWorker tutorial, did the following:
1) Started a gui
2) The gui had a start button that started a infinite thread of flipping a coin
3) Used publish to get results from the thread to the gui, showed number of heads, total flips, and 1/2-nHeads/total
4) Has a cancel button that cancels the thread
The revised code, copied below, does the following:
1) GUI expanded to show the results of 20 sets of flips, with the format "nHeads / nTotal / 0.5-nHeads/nTotal" displayed in each text box for the result from each of the worker threads.
2) Start button starts a manager thread. Current implementation the maneger sets the number of allowable threads equal to the number of processors
3) The manager thread manages worker threads that flip the coins, stopping when they reach a target of nFlips
4) The cancel button will stop the code, but the publish events will be behind, so a number of results will still be published after cancel is pressed.
5) The worker threads store the flips in a linked list so the results could be recalculated and checked against the real time results (recalculation was not implemented)
Some things that could be added
1) Input box to specify the number of flip attempts, currently hard coded to 1000000
2) A radio button to toggle between manager allowing Nprocessor simultaneous threads (current implementation) and allowing all threads to run simultaneously.
3) A timer that starts when start button is pressed, and stops when completed or when the last thread stops for cancel. Summary results should be shown, such as number of flips per second, and total number of flips for all workers
4) A comparison between the number of flips per second for nprocesssor threads and all treads running
5) Recalculation of the final (or intermediate) results from on the linked list of flips, and comparison between the post execution results with the "real time" results to validate that threads and messaging are implemented correctly
I would like to keep this question open until items 4 and 5 have been completed, since they seem to represent the fundamental question about accurate implementation of manager / worker threads.
Thanks for the suggestion on forkjoin, it does look like a flexible solution to the manager / worker threads with intensive computation problem. As you probably know, forkjoin was incorporated into Java 7.
I hope your are successful in efforts to improve the quality of Java 7. In my own experience, a few years back, I purchased a engineering software package that was upgraded to estimate a quantity that I had built a test facility to measure. When I ran the software, the results were not even close to hand calculations. I communicated with the company several times regarding the proper approximate and exact analytically formulation of the solution, and sent them test data from different facilities showing the deficiency. Throughout, the company maintained that they implemented the methodology correctly, and will continue to claim that their product estimates the quantity correctly. It was a strange experience, and we just parted ways. I think what I experienced was business management of a technology product.
Continuing the thread. The listing below adds some bells and whistles. I switched to Java 7, 64 bit, so the code runs quite a bit quicker here. But, I notice that when stop is pressed, the functioning thread runs to completion instead of aborting in the middle. I removed Java 6 from this machine. Could someone with Java 6 run the code below, and press start, wait, press stop. You should see %heads / %complete where %complete is less than 100. Today, I always get 100% for the completion. Yesterday, I was getting smaller number, but displaying the number completed instead of %. The code for cancel is at lines 184 (button action), 562 (manager cancel), 393 (worker cancel). Is this an error on my part, or in Java 7?
Eventually, I will follow your suggestions on implementing fork/join. Now, it appears I may want to uninstall 7.