This week's book giveaway is in the OO, Patterns, UML and Refactoring forum. We're giving away four copies of Refactoring for Software Design Smells: Managing Technical Debt and have Girish Suryanarayana, Ganesh Samarthyam & Tushar Sharma on-line! See this thread for details.
hello all, I've done a few little things with swing - enough to be somewhat familiar at least with some bits of it. However, one of the things I still can't quite get my head around is threading (I've read plenty of articles online but nothing has quite clicked for me yet).
I think my problem is understanding the design requirements and how things work so I'll give an example - if I have an im client that has one main window and multiple chat windows, is it necessary to have a main object that is the event dispatching thread, and have each chat window called from there using a swing worker class (so that it can be repainted as each new message comes in...?).
I'm sure this will sound pretty silly to those who do this quite a bit, but I'm just having a hard time getting my noggin around it. Any input or suggestions are greatly appreciated. thanks!
Threads let your program appear to do several things at the same time (whether those things actually happen at the same time or not depends on the number of CPU's, operating system and so on.). You use this kind of functionality all the time on a modern computer but you never think about it. For example, a web browser can display an HTML page while downloading the embedded images in the background. A VERY common question we get in this forum involves JProgressBar. People make a GUI with a button to kick off a long process (i.e a database query) and a progress bar to keep the user informed of the activity. When one presses the button, the button event handling code gets called by the swing event thread. If one simply calls the database query code from that event handler, the code executes on the swing event thread. This is the same thread used to update the GUI. Since the thread is busy with the database query it does not repaint the GUI. These people are then puzzled why their progress bar never gets updated. What they want want to do is both run a long process and update the gui. To do this simultaneously, you need to have two threads. I always point people with this problem to this thread. It has some good links to explain the problem and a number of thread-related solutions.
To answer your example more directly: you're thinking about it all wrong. I assume that since you've read articles you at least understand what a thread is and how threads work but aren't getting your head around how they function within Java in terms of the GUI.
You don't create the event-dispatching thread (EDT). Java starts several threads when the program starts up. One of them is the EventQueue or Event Dispatch thread where all Swing event-handling and painting code is run. So far, I'm sure you understand this, but it seems you're wondering what the implications are from there in a program such as the one you described.
What you have to understand is that if all event-handling code is run from the EDT that means any listeners you have will be called from that thread. Thus, any code you write that derives from those listeners will run in that thread as well, potentially holding up painting and other event-dispatching. So if you have an ActionListener on a button to open a new window, then when the user clicks that button the actionPerformed() method is getting called from the EDT and any code in it will be run in the EDT and any code that ends up calling will be run in the EDT. Thus, any code that takes a significant amount of time needs to be handed off to a new thread. Code then run from a different thread that alters the GUI needs to make special arrangements to have that section of its code run in the EDT using invokeLater or invokeAndWait for example.
I would strongly suggest a good debugger that will allow you to step through and view which thread code is running in such as the one with Eclipse. This will probably help you understand what code is running in which thread. It's actually a really simple concept with a whole lot of strings attached. Just remember two things: a) any code run in the EDT will prevent painting and event-dispatching from being run so it should be quick, b) any code NOT run in the EDT that attempts to modify the GUI in anyway should make special arrangements to have that part of the code run in the EDT using invokeLater or invokeAndWait.
In your specific example, you wouldn't create the EDT as I explained. What you would need to worry about is that when a message comes in that the code to update your IM window is run from the EDT. So, for example, you have a button to open a new IM window in your main window. They click it, actionPerformed() is called from the EDT and your code is now running in the EDT. You create a new window, display it, but now you have to handle sending and receiving messages and a log file. You decide that because they might have a great many IM windows open you better not run it all from the EDT and potentially choke it. You've already created your IM window, so you make a new thread and run newIMWindow(IMWindow) in that thread, we'll assume this method is something that takes the Component "IMWindow" and handles all the background code of sending/receiving/logging. Thus, your code for sending/receiving is now running in a different thread, so if a new IM comes in, the code will be handled in this thread NOT the EDT. Since all graphical changes need to be run in the EDT, when a new IM comes in you need to run the code for updating the GUI in the EDT using something like invokeLater().
Joined: Feb 10, 2005
Joe, thanks for your comments, they were helpful - I appreciate the link.
ken thanks very much, that was quite helpful - I think I still have a few things to muddle through but that helped clarify things for me.
appreciate the help! (I might revist this thread as I muck about with things and come up with more questions or identify flaws in my understanding )