The Artima Developer Community
Sponsored Link

Frank Thoughts
How Much Concurrency Should be Exposed in a UI Toolkit?
by Frank Sommers
June 12, 2007
Summary
Applications with a rich-client UI can benefit from concurrency. UI toolkits that expose concurrency, however, are not easy to use. Swing shows that the tension between concurrency and ease-of-use is hard to resolve. Just how much concurrency should be exposed in a UI toolkit?

Advertisement

Core Java author Cay Horstmann commented recently about the difficulty of using Swing's threading model correctly.

Difficulty is perhaps not the right word: Swing's concurrency rules are neither difficult to understand nor hard to follow. What is difficult, though, is to accept that one has to produce the kind of convoluted code required by those rules even for the simplest Swing application. As author of a Java tutorial, Horstmann's intent of showing attractive Java code is challenged when he gets to describing Swing development.

Swing's concurrency model is designed such that any change to component state must be performed from the Swing event-handling thread. That thread is created automatically when the Swing API boots, and each Swing release so far provided increasingly convenient means of injecting programmatic action into the event-handling thread, such as SwingWorker and SwingUtilities, now part of the core JDK 6 API.

Programmatic access means anything other than actions the end-user performs on a component. A user typing text into a text box is not programmatic access, and is automatically pushed onto the event-handling thread. Reading the values of that text box, by contrast, is programmatic access and, therefore, must be performed by explicitly injecting the reading action—the code for textBox.getText()—into the event-handling thread.

In his blog post, Horstmann shows some interesting consequences of this rule. Creating the UI of a Swing application, for instance, should not be performed in the main() method's current thread—instead, the developer must explicitly inject the UI-creating statements into the event-handling thread (this example is quoted from Horstmann's blog):

public class PureGoodness 
{
   public static void main(String... args)
   {
      EventQueue.invokeLater(new Runnable()
         {
            public void run()
            {
               JFrame frame = new JFrame(); 
               frame.setSize(300, 300); 
               frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
               frame.setVisible(true);
            }
         });
   }
}

This is not due to academic finickiness: Executing the UI-creating statements in the main() method may actually cause the UI to not show at all—or worse, like many concurrency-related errors, to show up as a heisenbug on users' desktops. This has actually happened in Swing applications I wrote some years ago.

Indeed, Swing's concurrency rule commands that even an action as simple as accessing a text field's value, or setting a label's text, be performed in a similar manner.

There are good reasons for this rule, which have been thoroughly explained by members of Sun's Swing team in various articles. Their main argument centers around considering the alternatives, compared to which Swing's threading model is still the best solution. Or so the Swing designers say.

One alternative, for instance, would be to make the Swing API thread-safe—an impractical option due to the performance penalty this would impose, not to mention the increased complexity of the API's implementation that almost certainly would lead to impaired stability.

Another alternative, practiced by Flex and Ajax applications, is to make the UI single-threaded. Since there is only one thread, by definition all updates are performed on that thread. A downside of the single-threaded approach is that the UI application cannot schedule long-running tasks in the background without locking up the UI. The single-threaded approach would also take away Java's sophisticated threading capabilities on the client. Indeed, one of the arguments presented in favor of a newly re-invigorated Swing on the client is the benefit of long-running tasks scheduled in a separate thread: For instance, executing image filters in an applet may make the UI more responsive if long-running filter algorithms ran in non-UI threads.

Swing's current threading model may well be the best compromise, but it's hard to deny that it requires a heroic effort form developers to carefully surround the relevant code with event-thread friendliness. This sort of tedium cries out for an API and, indeed, several third-party APIs make Swing-threading easier, such as Foxtrot and Spin.

I could finish this blog post here, saying that, Well, I understand the reasons for the Swing single-threaded rule, and I'm willing to live with that, perhaps using some of these third-party APIs.

However, I am too much of a Swing enthusiast to leave it at that. Now that Sun is finally taking client-side Java seriously, I suspect that many developers will wander into Swing territory with some Ajax coding under their belt. And I don't think the kind of code samples that Horstmann rightly points out as ugly would convert too many of them into Swing fans.

While most developers would intellectually understand the reasons for doing things this way, few would be able to accept that what's good for sophisticated Ajax applications—one execution thread—is not good enough for Swing. Many would, I suspect, question the extra amount of effort required in Swing coding compared to the code needed to develop similar features using some Ajax toolkit.

What can be done to make Swing programming easier? One solution might be to allow developers to use the threading model of Ajax applications when writing Swing code. When I spoke with Chet Haase, a member of Sun's Swing team, for an Artima interview, he pointed to Ajax's single-threadedness as a relative lack. But is it, really?

Trying my hands at Flex in the past couple of months, I realized that performing the UI's work in a single thread is not that much of a handicap. In fact, in most cases, it actually matches a user's expectations of an application. For example, loading data into the UI is one use-case often presented in Swing threading tutorials: Fetching data is performed in a worker thread, which leaves the UI event handling thread to respond to user actions. Yet, as long as the UI displays fast, a few seconds delay to get the data mimics not only the browser/Web application model, but also some desktop applications. When double-clicking on, say, the Microsoft Word icon on the desktop, the Word UI appears fairly fast, and it is in a separate step that the data—the Word document—is loaded into the application. There is really no need in that case to spin off a separate data-loading thread.

Does this example imply that the price of sophisticated concurrency in terms of API complexity is not worth paying? Not necessarily. It's just that a single-threaded UI model may satisfy the requirements of a large number of rich-client applications. And if that were, indeed, the case, simpler UI programming models will attract developers who prize ease-of-use above powerful concurrency. Swing should offer a simpler threading model to attract those developers. Exposing just a single thread of execution may be one way to achieve that.

Do you agree that the correct use of Swing's threading model induces complex and unattractive application code? If so, what do you think should be done to make the Swing programming model easier? How much concurrency do you think should be exposed in a UI toolkit?

Talk Back!

Have an opinion? Readers have already posted 34 comments about this weblog entry. Why not add yours?

RSS Feed

If you'd like to be notified whenever Frank Sommers adds a new entry to his weblog, subscribe to his RSS feed.

About the Blogger

Frank Sommers is a Senior Editor with Artima Developer. Prior to joining Artima, Frank wrote the Jiniology and Web services columns for JavaWorld. Frank also serves as chief editor of the Web zine ClusterComputing.org, the IEEE Technical Committee on Scalable Computing's newsletter. Prior to that, he edited the Newsletter of the IEEE Task Force on Cluster Computing. Frank is also founder and president of Autospaces, a company dedicated to bringing service-oriented computing to the automotive software market.

Prior to Autospaces, Frank was vice president of technology and chief software architect at a Los Angeles system integration firm. In that capacity, he designed and developed that company's two main products: A financial underwriting system, and an insurance claims management expert system. Before assuming that position, he was a research fellow at the Center for Multiethnic and Transnational Studies at the University of Southern California, where he participated in a geographic information systems (GIS) project mapping the ethnic populations of the world and the diverse demography of southern California. Frank's interests include parallel and distributed computing, data management, programming languages, cluster and grid computing, and the theoretic foundations of computation. He is a member of the ACM and IEEE, and the American Musicological Society.

This weblog entry is Copyright © 2007 Frank Sommers. All rights reserved.

Sponsored Links



Google
  Web Artima.com   

Copyright © 1996-2019 Artima, Inc. All Rights Reserved. - Privacy Policy - Terms of Use