 |
Microsoft Technical Summit, Threads, and Swing
Posted by javaben on April 09, 2005 at 12:51 PM | Comments (24)
Like a few other vocal bloggers, I attended the recent Microsoft Technical Summit (a.k.a. Developer Influential Seminar, a.k.a. Java/.NET Interop Event). I was warned beforehand that MS serves a lot of kool-aid at these events, and that's no joke -- I think they spiked the punchbowl.
I've waited to blog my own impressions until I've had a chance to digest what I've seen and let the "Wow" factor dissipate. I'll write up a few thoughts on the event here and there in coming weeks, starting with this entry.
I asked Anders Hejlsberg, creator and lead maintainer of C#, what lessons he learned from the C-Omega research project. His response was interesting:
"I don't think shared state will be a viable solution for concurrency; it doesn't scale -- there aren't enough Ph.D.s in the world."
He went on to say that he thought that the Servlet/ASP model of concurrency might be the future of a C# concurrency model; Servlet/JSP/ASP developers are largely insulated from the complexities of threading while the container does the heavy lifting.
This rings true with me. You see, I've gotten to know Swing very well over the past few years. While some advise Swing developers to avoid spawning threads as much as possible, developers wishing to create snappy, high-performance Swing GUIs will need to do the opposite: aggressively utilize an asynchronous multi-threaded architecture.[1]
And there-in lies the rub. As if the Swing API weren't complex enough, it turns out that wrangling with highly asynchronous multi-threaded code bumps up against some of the toughest problems in modern software development. Just ask the thread wizards of Javaland. And you were hoping VB ex-pats could start doing Swing development? Hah.
So of course, to get any large-scale Swing application off the ground, and have it perform well, you'll need some sort of framework that makes handling multiple threads easy. And there-in lies, err, another rub.
It turns out that there is no such framework for Swing[2]. Now, there are utilities here and there. SwingWorker, FoxTrot, Spin, Somnifugi (such as it is), and the upcoming and still-secret fancy-pants new uber-SwingWorker all promise to make the act of spawning the thread and then getting the updates back on the AWT thread easier.
But really, that's not the root of the problem. The problem is that developers have to worry about something that low-level in the first place.
For the past year or so, I've been noodling ways to make concurrency in Swing easier. I don't think making it easier to spawn a thread is the answer. I think removing the burden of worrying about threads is the answer. And how do we do that?
Container-managed Swing. That is, a framework where screens and event handlers are managed by a "container" that automatically handles threads. Asynchronous screen population in the background, expensive user operations spawned by event listeners -- all managed by a container that does the heavy-lifting (including disabling the interface and displaying progress, where appropriate).[3] Just as a Servlet developer doesn't concern herself with managing a pool of worker threads to handle incoming HTTP requests, a Swing developer shouldn't need to worry about managing threads. (Just as a Servlet container does a lot of other things, so should a Swing container -- but that's another blog entry.)
When I first implemented these ideas to support a Swing project, the notion of "container-managed Swing" was far from my mind. But after hearing Anders' remarks, I realized that its exactly what I had created.[4]
At No Fluff Just Stuff conferences throughout the year, and at JavaOne, I'll be sharing this idea (and a host of others) in more detail. When I first picked up Swing a few years ago, I was shocked to learn that virtually no literature existed discussing how to architect professional-grade Swing applications in any detail. Over the past few months, I've seen hints of such content gradually emerge. I hope my presentations and blog entries like this one can add meaningfully to the discussion.
Or, we could just implement DoEvents in Swing and let VB'ers work the way they've been working for years. (Hey, it'd be pretty easy... maybe it's not such a bad idea?) ;-)
===
[1] I have immense respect for the writers of the linked article. Managing threads is way too tricky for most Java developers. But, unfortunately, creating professional Swing applications demands it.
I just had this point re-emphasized yesterday. I was sitting on a light-rail train when I bumped into an old friend. He was talking about an app he was using (which I knew to be Swing-based). He said, "It's way too slow!" They upgraded all their computers (more memory, faster processor, faster video card) to fix the problem, and guess what? It didn't get any faster. Standard symptoms for under-aggresive use of threads with Swing.
[2] NetBeans includes a dumbed-down version of SwingWorker in its API, and Spring RCP leaves threading as an exercise for the developer. (Though given the lack of documentation for both projects, I could be wrong and I'd love to know if I am.) Besides, both platforms aren't ready for prime-time. NetBeans has very little documentation indicating how to use it as a platform, and Spring RCP development has been stalled for some time and has yet to make a formal release of any kind.
[3] JFace certainly makes life a lot easier than any of the Swing frameworks I've seen, and Eclipse RCP adds more to the picture. But, that's only if you're using SWT, and besides, those frameworks don't quite go far enough. But, more on that in another blog.
[4] I really don't know if I like the "container-managed" label or not. It's just that "framework" is so ambiguous as to be meaningless. So for now, I think I'll keep using it.
Bookmark blog post: del.icio.us Digg DZone Furl Reddit
Comments
Comments are listed in date ascending order (oldest first) | Post Comment
-
Your project sounds exciting, if it works. I don't understand the way it works. I think the solution to most threading problems is separating functionality into a graph of dependent code, which some manager uses to determine what can be run simultaneously.
Posted by: keithkml on April 09, 2005 at 01:27 PM
-
Ah yes, the details. In a nutshell, the framework has a top-level container that manages individual screens. Screens in the application utilizing the framework are subclasses of an abstract parent screen class, and the subclasses initialize themselves using the "Template Method" pattern (that idea is borrowed from JFace, which also uses that pattern extensively).
The top-level container manages the lifecycle of the screens. Of interest to this blog entry is its support for either displaying a loading animation while a screen initializes in the background (and allowing for cancellation of the screen, etc.), or displaying loading animations in portions of the screen while those portions initialize in the background but other portions of the screen allow for user input.
The framework also provides enhanced event handlers which also use the Template Method pattern to allow developers to give developers a simple way to put their expensive operations in background threads. The template contract makes it explicitly obvious exactly where to put user code, etc. The container takes care of the threading issues.
It's actually all a bit more complex than this -- there are more actors in the framework than a top-level container and a screen, as well as what I've called "enhanced event handlers", but describing everything would be more work than I have at the moment. But, I hope this comment has shed a little more light on the implementation details.
Posted by: javaben on April 09, 2005 at 01:39 PM
-
You discuss event listeners and asynchronous screen population. This is exactly what Glazed Lists does for JTables and JLists. Here's how it works:
1. A background thread does the slow I/O stuff, such as downloading the table's rows.
2. Whenever an element is ready, it is added to a list of elements. This list's add() method fires an event.
3. A listener receives the event and forwards it on the Swing thread using invokeAndWait().
4. Your JTables and JLists receive the forwarded event and render the new element.
To the application programmer, the thread proxying is completely transparent. You can see this in action in the web start demo.
Cheers,
Jesse
Posted by: jessewilson on April 09, 2005 at 07:05 PM
-
Hey Jesse,
Thanks for the pointer. I like Glazed Lists; I mention them in my presentations. They certainly can be a good addition to a more comprehensive framework's bag of tricks.
Posted by: javaben on April 09, 2005 at 09:16 PM
-
What about forcing the GUI updating code to run into swing thread using AOP?
Posted by: sevenm on April 11, 2005 at 06:54 AM
-
"Any sufficiently easy to use GUI framework will simply have to reinvent VB... and badly"
Seriously, we could learn a lot from VB 3 and 5 (4 was a mishmash, 5 was the last good version of VB, everything after that is an abomination that causes desolation).
VB is a bad language, with an amazing IDE. Of course even with a good IDE its still all too easy to create a bad looking app. But all the lessons about how to make a VB app look good (or at least less horrible) *also* apply to Java.
In particular, the important thing is not how many *actual* clock cycles are used, but how the user perceives it. A friend of mine who is an optimizer to the umpteenth degree was sweating blood trying to *somehow* crank an extra couple of percent out of his app because the user feedback consistently said that it was 'way too slow'. So I asked him if it was fast, and he said that yes... it was fast. Now you've got to understand this guy, if he said it was fast, it was damn fast.
So I suggested that he make it 'shiny'. In particular, I sugested that he leave it exactly the way it is, but put up a splash screen at the start (old VB trick). He of course said that that would make it slower! I said of course it will make it slower, but to the user it may *feel* faster... and besides, at this stage he had nothing to lose (he was talking about moving stuff into assembler and accessing it through JNI he was that desperate).
A couple of days later, he calls me back and with shock and awe in his voice he tells me that the splash screen worked... the users all now mysteriously loved the app... and they said it was now much faster than before...
Having a fast Java app isn't all that hard. Heck, threads in swing isn't all that hard either. Yes... its a little harder than DoEvents. And swing does behave a little oddly at startup sometimes (you kind of have to jiggle the initialization around a bit, and its true that combo boxes in particular are a little nasty and skanky).
You just have to know all the good old HCI tricks. HCI is much more important in most cases than raw speed. Otherwise how would Microsoft's own really really slow interpreted language (VB) have gotten so much more market share than its blazingly* fast compiled language (Visual C/C++)??
*well... blazingly fast compared to VB, 'blazing saddles'-like when compared to other compiled languages I'm sure.
Posted by: rickcarson on April 11, 2005 at 07:41 AM
-
Very good idea. There are probably other things a container could provide to make application development easier as well. Perhaps some IoC type features for common dependencies such as getting the active window. Basically, you
Posted by: scottdelap on April 11, 2005 at 07:47 AM
-
If I was in charge of developer programs at Microsoft I would be calling this last event a success by the number of Java developers they could actually get to attend. Of course nothing wrong with that. One of Microsoft's biggest issue is that they are actually lagging Java and marking time waiting for Visual Studio/longhorn.
If only Sun could spend just 1% of the 2 billion settlement with Microsoft on doing the same. Trust me I asked many times and the answer was always no.
Posted by: calvinaustin on April 11, 2005 at 10:01 AM
-
Count me in as a supporter. I generally write webapps, but the one serious Swing app I did write was a wonderland of threads. Keeping track of whether or not I was in a thread that could update the GUI was quite maddening! I don't know what's needed to simplify that, but until that situation is clarified, I'm giving Swing a wide berth in my future projects.
Posted by: tomwitmer on April 11, 2005 at 11:36 AM
-
How about calling it "Inversion of Interface"? Or maybe "SwingAxe"?
So, what would be the description of the application provided to the container? Would it be a XUL-type markup? I've often thought that the Swing component model is pretty bad with respect to seperation of concerns ... for efficiency reasons, the components are responsbile for lots of concerns: drawing, positioning/layout, creation/instantiation, interactivity. An approach based on peers might be the right direction to go in, though how that differs from todays morass of models, renderers, inner classes and layout managers I can't say.
Posted by: hlship on April 11, 2005 at 01:43 PM
-
It's a great point that Mr. Hejlsberg makes about "not enough PhDs" for shared-state concurrency to work. Even great books about threading follow this depressing format: 3 pages about what threading can do, 300 pages about the problems multiple threads create.
(By the way, Mr. Galbraith's presentation on javalobby about threading and swing is a great intro / refresher on the issues discussed here.)
Posted by: kj12345 on April 11, 2005 at 06:07 PM
-
Your approach to shield the developer from threading issues in SWING is absolutely on the mark. We desperately need this, if Java wants to be the platform for desktop development. There is huge business power in that market! I have met so many VB developers who have constructed complicated business applications with VB who simply don't care about the finer art of prgramming. Whenever I tried to help them getting comfortable with SWING they were annoyed, frustrated and their code often did not work. (Database access in the AWT Event Queue, anyone?) The damage done to "Java" is huge, huge, huge! Of course, these guys don't want to be told that it's their lack of understanding. These guys want to do some serious hack and slay, best with a chainsaw. Again, the question is, do we all want to go there?
Posted by: norb on April 11, 2005 at 11:27 PM
-
If you decide to create an open source project to develop the ideas outlined above, you can count on me as a helping hand. I'm developing Swing apps daily and I do really think it's a very good idea to develop such a framework.
Posted by: aaime on April 12, 2005 at 12:37 AM
-
Vic Cekvenich is probably furthest down the road in developing a threaded framework for Swing using MV*C* Great code!
More on www.sandrasf.com/download
Or contact netsql*AT*roomity.com
Wolfgang Gehner, co-author Struts Best Practices
Posted by: wgehner on April 12, 2005 at 01:06 AM
-
I'll reply to several comments here.
sevenm: I've chatted briefly with Ramnivas Laddad about doing something like that. I'll have to actually implement it and see how well it works. It would replace the need for a framework, but it would obviate the need to separate GUI updates from background user operations.
rickcarson: Heh. The lesson of VB is that tools matter. Fortunately, there's some great innovation happening in the Swing tools front. That's another blog entry. Of course you're right -- user perception is very, very important. I rant about this often when I'm in front of people. Another lesson from VB is that absolute positioning probably should be kept as an option for folks willing to take the productivity gains in exchange for some decreased amount of platform independence. But, let's also remember the huge limitations of VB, and be greatful for the flexibility of Swing. I think a lot of folks romanticize the past. I have a VB6 license. I don't see myself using it anytime soon.
scottdelap: Yep! There are a lot of things a container can do. Lifecycle management, thread throttling, resourcing management (including caching), and so forth. I'll have to do another blog talking about some more of the details of what I've done, and I'd love to see the rest of your comment to get some more ideas from you.
calvinaustin: Ted Neward published a rant a while ago complaining about Sun's lack of an MVP program equivalent. I think Sun's attitude might be, "We are open, anyone can participate." whereas MS' attitude might be, "Let's make developers feel like they're participating." Having infinite amounts of money helps too. But it would be interesting to see Sun court developers more. Having some kind of developer advisory panel might have prevented the huge mistake of not introducing good tools until 2005.
hlship: Heh... love the names man. The framework I've developed lets you (a) hand-code application screens, (b) use XUL, or (c) use a GUI editor and save GUIs into a binary format (like NIB files) that are loaded at run-time. No tools are out there that work quite like Interface Builder for defining bindings at design-time, so I've experimented with name-based binding. Give a button a name, like "foo" and have a handler named "FooAction" and the framework links the two up. That's actually worked pretty well. You can choose to make the bindings explicitly, of course.
I could factor the "flow" of the application out of code itself, but in my experience, most developers want to statically define application flow. I suspect next time we're in a room together it would be fun to chat about this.
norb: Yeah, time after time I run into folks who have built Swing applications the wrong way. Smart folks. It's pretty sad; something needs to be done.
tomwitmer, aaime: I appreciate the support. I have thought about taking the framework ideas I've implemented and re-implementing them as an open-source project. I'll do some more thinking about that.
Posted by: javaben on April 12, 2005 at 06:01 AM
-
wgehner: I've already implemented a bunch of ideas in production code and have re-implemented the ideas again for a client in a framework that is being used to create production code. So, I don't know if its fair to say that Vic is "furthest down the road." I'll have to take another look at his stuff; last time I did, it was dependent on JDK 5, undocumented, and source wasn't available.
I'm still waiting for the JavaLobby presentation he promised to create that he alleged would show the world why my (non-controversial, straight-forward) Swing presentations on JavaLobby were completely wrong. That was, oh, 6 months ago?
Hmm...
Posted by: javaben on April 12, 2005 at 06:08 AM
-
Sorry Ben, I didn't mean to challenge you in any way (nor was I aware that he apparently had challenged you on something). I was looking through your blog for a link to your open source project that implements what you hint at in your post., couldn't find it (your latest post explains why), so just proposed to the community an additional (interesting, IMHO) source to look up on the topic. I've seen Vic's code as early as October last year, and I liked very much what I saw. I'd *love* to take a look at your stuff as and when you put it up under Apache license. Vic's license I think is "quasi-Apache", just adding attribution.
Posted by: wgehner on April 12, 2005 at 06:50 AM
-
Ben guess my comment was cut off. I was saying that a container would enforce a pattern of programming that would promote thread safe Swing applications. SwingWorker bascially does this without handling the UI related progress properties. If nothing else a good API similar to Eclipse's Jobs API would be a welcome addition to Swing apps that need to run many asynchronous tasks.
Posted by: scottdelap on April 12, 2005 at 07:47 AM
-
Ben, are you still thinking of releasing this framework as an open source project?
Posted by: awf999 on June 17, 2005 at 07:18 PM
-
awf999: I am, yes. I'm using the framework for demos in my upcoming prezo at JavaOne and chatting with some folks in the coming weeks about the framework's future. I'll make an announcement if I do open source it.
Posted by: javaben on June 18, 2005 at 10:15 AM
-
Ben, did you see that the new SwingWorker code has been released?
https://swingworker.dev.java.net
Posted by: awf999 on June 20, 2005 at 07:34 AM
-
I am interested in this. I had played around with a similar idea several years ago, but I FAILED. All views had to be subclassed from some class (at least I was certain that they did back then) and it seemed that the user had to commit to far too much up front without knowing whether any returns would arrive later.
I had a data structure holding all views. Given the "current" view and an integer code (which corresponded to the button pressed) gave one the "next" view to be loaded. And the background thread would rip out the current view from the frame, substitute a blank wait view, perform some task (which could be lengthy), and then repopulate the frame with the "next" view. I thought that I had obviated the need for messy/hardcoded view reloading following UI interaction, but I never really figured out how to change that datastructure at runtime for those situations where UI paths change (if that makes any sense). Additionally, I would occasionally "lose" events and that sucks BIGTIME; when you click a button, you do expect something to happen.
Because of the problems I ran into, I was always unsure whether my framework was truly a first class multi-threaded citizen of Swing. Again, it was ponderous and I concluded that a framework can fail if you have to marry it before you can get to first base.
Posted by: jonniesavell on July 02, 2005 at 12:28 PM
-
>So of course, to get any large-scale Swing application off the >ground, and have it perform well, you'll need some sort of >framework that makes handling multiple threads easy.
>It turns out that there is no such framework for Swing[2].
I developed such a framework for Swing called SwingForms.
NO gui freezes!
It does not use Foxtrot or Spin, I do use SwingWorker but that's just to be 'safe' I could do without...
Ben I would like to talk to you about my solution if you like?
Regards,
Will
www.coderight.nl
Posted by: wlboluyt on July 05, 2005 at 01:05 PM
-
I have started working on a client container project. Its goal is to simplify swing developement, by leveraging an Inversion of Control (IoC) container, Picocontainer, and Java 5.0 annotations, and the JGoodies libraries.
Version 0.1 has been released, and there is a little demo where you can test it and see how it works. Please help me on this project by providing feedback and ideas.
http://sourceforge.net/projects/clico
Support for threading is planned for the 0.2 release, with the help of Foxtrot and/or SwingWorker
Ludovic
---
Posted by: ludovicc on July 17, 2005 at 04:35 AM
|