[java] threads
i'm in the process of learning swing so instead of just writing a GUI that doesn't do anything, i decided to write an application that actually does something.
everything works great apart from that i don't know how to use threads. the thing is that one operation "freezes" the gui. i know this can be solved by using threads for the processor hungry operation, just not how.
i have these classes:
Main // doh
GUI // the gui. extends JFrame
Application // this is where the calculations are done
(more classes, but these aren't important)
Main creates a new Application. Application calls the GUI and when the user performs a certain action, a cpu hungry operation performs some calculations. I'd like to run this in a new thread instead of the main thread so that i won't lock up the GUI.
any ideas how to implement this or where to find more information? i've checked java.sun.com, but i weren't able to adapt their examples to suit my needs.
_______________________________
catch (SpellingException e) {}
Edited by - mill-o on November 9, 2001 7:54:46 AM
Edited by - mill-o on November 9, 2001 8:26:44 AM
When the user click on a button, launch a thread (have a look to the Thread class in the JDK) that will do all the operations without blocking the whole GUI. You may need to disable some widgets until the operation is complete to prevent the user from launching too many threads.
Edited by - Prosper/LOADED on November 9, 2001 9:01:03 AM
Edited by - Prosper/LOADED on November 9, 2001 9:01:03 AM
thanks for the fast reply. i''ll give it a try right away.
______________________________
catch (SpellingException e) {}
______________________________
catch (SpellingException e) {}
ok.. now Application extends Thread, meaning that when I create a new Application I create a new thread? the GUI is still not updating. i even tried app.setPriority(app.MIN_PRIORITY), but that didn't help either. all that happened is that the task took ~20000 ms instead of ~8000 ms. you can see the code below:
in Application all the job is done in the run-method, which I suppose is correct.
any ideas, anybody?
______________________________
catch (SpellingException e) {}
Edited by - mill-o on November 9, 2001 2:27:28 PM
if (returnVal == JFileChooser.APPROVE_OPTION) { File foo = fc.getSelectedFile(); Application app = new Application(foo); app.start(); createProgressMonitor(); while (!app.isDone()) { progressMonitor.setProgress(app.getProgress()); } output.append(app.getResult());}
in Application all the job is done in the run-method, which I suppose is correct.
any ideas, anybody?
______________________________
catch (SpellingException e) {}
Edited by - mill-o on November 9, 2001 2:27:28 PM
If your goal is to update a progress bar while processing, u might wanna have a look at Class Observable and Interface Observer.
There''s also some articles/tutorials on java.sun.com/docs describing how to use them.
There''s also some articles/tutorials on java.sun.com/docs describing how to use them.
Well, you''re doing a couple of things wrong. First off, you are updating a swing component from the event dispatch thread (the thread that calls your event listeners). Always update Swing compoents from other threads. Do this by passing your progressMonitor to the new Application when it''s created, and update the monitor in the run method whenever appropriate.
This also removes the need for the while loop, letting the event dispatch thread go about its business (repainting components & the such) while you do the stuff in app.run().
Of course, if progressMonitor or output (or anything else for that matter) are shared between different threads, be sure to place locks around them so that 2 threads don''t modify each other''s data. Do a search for "synchronized" on Goolge or Sun''s Java site for more info.
"So crucify the ego, before it''s far too late. To leave behind this place so negative and blind and cynical, and you will come to find that we are all one mind. Capable of all that''s imagined and all conceivable."
- Tool
This also removes the need for the while loop, letting the event dispatch thread go about its business (repainting components & the such) while you do the stuff in app.run().
if (returnVal == JFileChooser.APPROVE_OPTION){ File foo = fc.getSelectedFile(); createProgressMonitor(); Application app = new Application(foo, progressMonitor, ouput); app.start();}// ... In Application.run()public void run (){ // ... Load data or do calculations progressMonitor.setProgress(getProgress()); // ... Load more data or do more calculations progressMonitor.setProgress(getProgress()); //... output.append(getResult());}
Of course, if progressMonitor or output (or anything else for that matter) are shared between different threads, be sure to place locks around them so that 2 threads don''t modify each other''s data. Do a search for "synchronized" on Goolge or Sun''s Java site for more info.
"So crucify the ego, before it''s far too late. To leave behind this place so negative and blind and cynical, and you will come to find that we are all one mind. Capable of all that''s imagined and all conceivable."
- Tool
thanks a lot WayfarerX. the gui is responding now and the PogressMonitor is updating properly.
______________________________
catch (SpellingException e) {}
______________________________
catch (SpellingException e) {}
quote:First off, you are updating a swing component from the event dispatch thread (the thread that calls your event listeners). Always update Swing compoents from other threads.
This is exactly wrong... It creates MANY race conditions in your code. Anything that updates a GUI component from any thread other than the dispatching thread should use SwingUtilities.invokeLater(Runnable) to execute the updates in the GUI thread.
mkay, i tried that. Application now implements Runnable instead of extending Thread. Application is now called as can be seen below:
The GUI and the ProgressBar don''t update properly now. I guess I didn''t understand you totally..
______________________________
catch (SpellingException e) {}
if (returnVal == JFileChooser.APPROVE_OPTION) { createProgressMonitor(); output.setText(""); javax.swing.SwingUtilities.invokeLater(new Application(fc.getSelectedFile(), progressMonitor, output));}
The GUI and the ProgressBar don''t update properly now. I guess I didn''t understand you totally..
______________________________
catch (SpellingException e) {}
Yeah, you misunderstood...
Definately run the logic in a separate thread. However, when you need to update swing components from that thread, use SwingUtilities.invokeLater(Runnable) to update the swing components, and NOTHING else.
Like this:
Unfortunately, that will take a small bit of fiddling to get to work properly, as the value v that the progress bar is being update with will either have to be final (in which case it will have to be declared and initialized right before the call to invokeLater), or it will need to not be a local variable.
Definately run the logic in a separate thread. However, when you need to update swing components from that thread, use SwingUtilities.invokeLater(Runnable) to update the swing components, and NOTHING else.
Like this:
// do some calculations// update progress bar:SwingUtilities.invokeLater(new Runnable(){ public void run() { progressbar.setValue(v); progressbar.repaint(); }});// do more calculations, and probably loop back to up above
Unfortunately, that will take a small bit of fiddling to get to work properly, as the value v that the progress bar is being update with will either have to be final (in which case it will have to be declared and initialized right before the call to invokeLater), or it will need to not be a local variable.
This topic is closed to new replies.
Advertisement
Popular Topics
Advertisement