The Artima Developer Community
Sponsored Link

Weblogs Forum
How Much Concurrency Should be Exposed in a UI Toolkit?

34 replies on 3 pages. Most recent reply: Jun 21, 2007 8:41 AM by Achilleas Margaritis

Welcome Guest
  Sign In

Go back to the topic listing  Back to Topic List Click to reply to this topic  Reply to this Topic Click to search messages in this forum  Search Forum Click for a threaded view of the topic  Threaded View   
Previous Topic   Next Topic
Flat View: This topic has 34 replies on 3 pages [ 1 2 3 | » ]
Frank Sommers

Posts: 2642
Nickname: fsommers
Registered: Jan, 2002

How Much Concurrency Should be Exposed in a UI Toolkit? (View in Weblogs)
Posted: Jun 12, 2007 4:05 PM
Reply to this message Reply
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?


Ronald Tetsuo Miura

Posts: 22
Nickname: ronaldtm
Registered: Jan, 2004

Re: How Much Concurrency Should be Exposed in a UI Toolkit? Posted: Jun 12, 2007 6:08 PM
Reply to this message Reply
You can program single-threaded Swing apps, can't you? Well, you still have to post the main frame's creation to the EventQueue, but that's pretty much it. You just put everything called directly from UI listeners, without worrying about threading. The screen still hangs on long processing actions, but the old 'gray screen of death' doesn't appear anymore.

You use only threads if you do want to make the UI more responsive during these long processing actions, the same way you would with Javascript ('AJAX').

Daniel Jimenez

Posts: 40
Nickname: djimenez
Registered: Dec, 2004

Re: How Much Concurrency Should be Exposed in a UI Toolkit? Posted: Jun 13, 2007 6:59 AM
Reply to this message Reply
I was on a project where the team was new to Swing. One of QA's favorite bug reports was that alt-tabbing off of the app then back would leave a big gray box in the app (screen updates wouldn't occur until the long-running task finished). Multi-threading wasn't an option there.

Honestly, though, I always found client-side coding to be more fun because of the ability to write multi-threaded code. The negative, of course, is that everyone is a UI expert ...

Morgan Conrad

Posts: 307
Nickname: miata71
Registered: Mar, 2006

Re: How Much Concurrency Should be Exposed in a UI Toolkit? Posted: Jun 13, 2007 5:00 PM
Reply to this message Reply
I strongly believe that all non-trivial throwaway Swing widgets should call Actions, not be coded in place.

The super-advantage is that if the Action is disabled, for example, nothing is open so you can't Save, then ALL widgets associated with that action are disabled. And they all share the same text, icon, tooltip, which, in general, is what you want. And when there is a last minute change in the tooltip it's easy to change.

Also, you have a central place for your own subclass of AbstractAction to handle internationalization, etc...

Now, if your subclass of AbstractAction also implemented Future (or something like Future) it could also handle the asynchronicity. This subclass could also have standard methods for fireing events, stopping, preventing re-entry, etc. I largely implemented this for a Swing-based project and it seemed to be the right approach. The project was cancelled so it never got completely tested to find any weaknesses.

Inside actionPerformed() you had

before(); which was guaranteed to run on the UI thread, say, to put up an "Are you sure dialog".
doit(); which may or may not be on a separate thread, depends on the subclass impl
after() which was guaranteed to run on the UI thread, e.g. to close down a progress dialog and update the UI.

which were all abstract or do-nothings intended to be overriden.

I've seen similar approaches elsewhere so this isn't completely unknow or original.

Jeff Ratcliff

Posts: 242
Nickname: jr1
Registered: Feb, 2006

Re: How Much Concurrency Should be Exposed in a UI Toolkit? Posted: Jun 13, 2007 5:51 PM
Reply to this message Reply
> You can program single-threaded Swing apps, can't you?

I thought that one truly unique feature of Swing is that you can't do single-threaded GUI apps because the GUI is always on a different thread than your main thread.

There may be somewhat convenient ways to deal with it, but it's still multi-threaded.

Jeff Ratcliff

Posts: 242
Nickname: jr1
Registered: Feb, 2006

Re: How Much Concurrency Should be Exposed in a UI Toolkit? Posted: Jun 13, 2007 6:19 PM
Reply to this message Reply
> <p>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.

I think the assumption is that you have to do multi-threading the Swing way or drop back to single-threaded, but that's not true. If the GUI shares the main thread, it doesn't stop you from creating additional threads to do work in the background. Then you get the best of both worlds: GUI applications with short processing times can enjoy the simplicity of a single-threaded model while more sophisticated GUI applications that need to perform work in the background can create additional threads to keep the GUI responsive.

I think the Swing approach is typical Sun: they know that every GUI application should be multi-threaded, so they saw no reason to offer an alternative.

Ronald Tetsuo Miura

Posts: 22
Nickname: ronaldtm
Registered: Jan, 2004

Re: How Much Concurrency Should be Exposed in a UI Toolkit? Posted: Jun 13, 2007 7:28 PM
Reply to this message Reply
> > You can program single-threaded Swing apps, can't you?
>
> I thought that one truly unique feature of Swing is that
> you can't do single-threaded GUI apps because the
> GUI is always on a different thread than your main
> thread.
>
> There may be somewhat convenient ways to deal with it, but
> it's still multi-threaded.

But couldn't you let the main thread only call EQ.invokeLater() and die, then use just the EDT for all the application?

Anyway, in a typical application, after creating the main frame, won't all processing be triggered by component events (buttons, menus, etc.), thus run in a single thread (EDT) by default?

Frank Sommers

Posts: 2642
Nickname: fsommers
Registered: Jan, 2002

Re: How Much Concurrency Should be Exposed in a UI Toolkit? Posted: Jun 13, 2007 8:02 PM
Reply to this message Reply
> But couldn't you let the main thread only call
> EQ.invokeLater() and die, then use just the EDT for all
> the application?
>
> Anyway, in a typical application, after creating the main
> frame, won't all processing be triggered by component
> events (buttons, menus, etc.), thus run in a single thread
> (EDT) by default?

The application can lock up, unless you explicitly push UI events to the event handling threads. For instance, if you want to change the text of a label ( when displaying a message to the user, for instance), that has to be done on the event thread, too.

Not following this rule is a very common Swing programming error, and it leads to unexpected app failures. I encountered this when I developed a fairly big Swing app a few years ago. Even if you're very careful, you can introduce programming errors of this kind. There are some tools now that help you discover those errors.

Frank Sommers

Posts: 2642
Nickname: fsommers
Registered: Jan, 2002

Re: How Much Concurrency Should be Exposed in a UI Toolkit? Posted: Jun 13, 2007 8:11 PM
Reply to this message Reply
Completely serendipitously, I came across a relevant set of slides today from a presentation by John Oesterhaut, <a href="http://home.pacbell.net/ouster/threads.pdf">Why Threads Are A Bad Idea (for most purposes)</a> (PDF). This is from 1996, and compares here the thread-based vs event-based models in UIs especially. The event-based model is used in Ajax and Flex UIs.

This is something that a lot more people are brining up these days, e..g, with <a href="http://www.ibm.com/developerworks/java/library/j-cb04186.html">Erlang- style concurrency</a> or <a href="http://lamp.epfl.ch/~phaller/doc/ActorsTutorial.html">Scala actors</a>.

Note that Oesterhaut, inventor of Tcl, was also author of <a href="http://home.pacbell.net/ouster/scripting.html">Scripting: Higher Level Programming for the 21st Century</a>, which he wrote back in 1998, before enterprise developers seriously started to look at scripting languages, Ruby, or before JDK scripting access, etc.

Interesting that Oesterhaut worked for Sun at the time.

Ronald Tetsuo Miura

Posts: 22
Nickname: ronaldtm
Registered: Jan, 2004

Re: How Much Concurrency Should be Exposed in a UI Toolkit? Posted: Jun 13, 2007 8:38 PM
Reply to this message Reply
Well, nothing better than code:

import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
 
public class SimpleApp implements Runnable {
    public static void main(String[] args) throws Exception {
        // main thread starts
        EventQueue.invokeAndWait(new SimpleApp()); // adds the initialization callback to the EDT queue
        // main thread dies
    }
    public void run() {
        // runs in the EDT
        final JTextField text = new JTextField(10);
        final JLabel label = new JLabel("0");
        
        JButton button = new JButton("Fibonacci");
        button.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                //This is called in result of a component event (button click),
                // thus, runs in the EDT as well
                System.out.println(Thread.currentThread()); // prints "Thread[AWT-EventQueue-0,6,main]"
                
                // this can take some time, and the EDT blocks.
                // but, thanks to the Swing team, in Java 6 the frame will not
                // show an uglu gray rectangle (will just freeze its last view)
                
                long n = Long.parseLong(text.getText());
                label.setText(String.valueOf(fibo(n))); // safe to change component
            }
        });
        
        JFrame f = new JFrame();
        f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        f.setLayout(new GridLayout(1, 3));
        f.add(text);
        f.add(button);
        f.add(label);
        f.pack();
        f.setVisible(true); // the visible frame will keep the EDT and the application alive
    }
    static long fibo(long n) {
        if (n==0) return 0L;
        if (n==1) return 1;
        return fibo(n-1) + fibo(n-2);
    }
}


Just the initial invokeLater() call runs outside the EDT, everything else runs in the EDT, because they are triggered by component events.

If everything in the application runs in the EDT, why can't it be considered single-threaded?

Ronald Tetsuo Miura

Posts: 22
Nickname: ronaldtm
Registered: Jan, 2004

Re: How Much Concurrency Should be Exposed in a UI Toolkit? Posted: Jun 13, 2007 8:50 PM
Reply to this message Reply
> Completely serendipitously, I came across a relevant set
> of slides today from a presentation by John Oesterhaut,
> Why Threads Are A Bad Idea (for most purposes)</a> (PDF).
> This is from 1996, and compares here the thread-based vs
> event-based models in UIs especially. The event-based
> model is used in Ajax and Flex UIs.

What I don't get is why do you consider Swing is not event-based? All event handlers ARE called in the EDT, not in some random thread.

You only get the multiple threads problem if: 1. you use the main thread (the main() method thread) to manipulate Swing components (you avoid it simply calling invokeLater() to do all the work); or 2. you create your own threads (well, you must know what you are doing, anyway).


> This is something that a lot more people are brining up
> these days, e..g, with Erlang-style concurrency or Scala
> actors.
>
> Note that Oesterhaut, inventor of Tcl, was also author of
> Scripting: Higher Level Programming for the 21st Century,
> which he wrote back in 1998, before enterprise developers
> seriously started to look at scripting languages, Ruby, or
> before JDK scripting access, etc.
>
> Interesting that Oesterhaut worked for Sun at the time.

I agree that threads/synchronization are not the ideal concurrency abstraction for many tasks, but they are still useful. And well, they are part of the language, so we can't just throw it away :)

Jeff Ratcliff

Posts: 242
Nickname: jr1
Registered: Feb, 2006

Re: How Much Concurrency Should be Exposed in a UI Toolkit? Posted: Jun 13, 2007 9:41 PM
Reply to this message Reply
> Just the initial invokeLater() call runs outside the EDT,
> everything else runs in the EDT, because they are
> triggered by component events.
>
> If everything in the application runs in the EDT, why
> can't it be considered single-threaded?

Assuming there are no issues, you've successfully created a multi-threaded Swing application that kills one of the threads early, but it's still not single-threaded.

I guess if you wanted to categorize the "threadedness" of an application using fuzzy logic, you could say that your code example has a smaller membership in the multi-threaded set than most Swing apps do.

Timo Stamm

Posts: 3
Nickname: tstamm
Registered: Jun, 2007

Re: How Much Concurrency Should be Exposed in a UI Toolkit? Posted: Jun 14, 2007 11:50 AM
Reply to this message Reply
We just need first class functions with a decent syntax:
JButton button = new JButton("Fibonacci");
button.addActionListener({
  long n = Long.parseLong(text.getText());
  label.setText(String.valueOf(fibo(n)));
});
There are several proposals for something like that.


But what about JavaFX? It is marketed as yet another RIA toolkit, competing with AIR and Silverlight. Nobody seems to notice that it solves Swings largest problems. I am quite sure that JavaFX will become the way to write all kind of Swing apps.

Ronald Tetsuo Miura

Posts: 22
Nickname: ronaldtm
Registered: Jan, 2004

Re: How Much Concurrency Should be Exposed in a UI Toolkit? Posted: Jun 14, 2007 12:28 PM
Reply to this message Reply
> We just need first class functions with a decent syntax:
>
> JButton button = new JButton("Fibonacci");
> button.addActionListener({
>   long n = Long.parseLong(text.getText());
>   label.setText(String.valueOf(fibo(n)));
> });
> 
There are several proposals for something like
> that.

Well, this simplifies the code, but doesn't solve the multithread problem.


> But what about JavaFX? It is marketed as yet another RIA
> toolkit, competing with AIR and Silverlight. Nobody seems
> to notice that it solves Swings largest problems. I am
> quite sure that JavaFX will become the way to write
> all kind of Swing apps.

I think it tries to compete mainly with Flash, as a rich and dynamic 'applet' embedded in web pages, or applications for modern mobile devices. End-user, consumer apps. Nice to do animations, and if it gets proper tooling, it'll be easier for (visual) designers to get to it than to Java/Swing.

But, in 'enterprise' applications (those that run inside an intranet, in controlled environments, niche where Swing appeals today), where fancy graphics and animations don't matter that much, I don't see it getting much traction. Well, unless it becomes REALLY easy to make good UIs with it (including forms, tables and other 'enterprisey' stuff).

Achilleas Margaritis

Posts: 674
Nickname: achilleas
Registered: Feb, 2005

Re: How Much Concurrency Should be Exposed in a UI Toolkit? Posted: Jun 15, 2007 6:42 AM
Reply to this message Reply
Computations which take time should be executed in a different thread, so as that the UI remains responsive. Short computations should be executed in the same thread as the GUI.

It's a simple rule really, and I don't know why is there a topic in Artima about this. What's more to say on this?

Flat View: This topic has 34 replies on 3 pages [ 1  2  3 | » ]
Topic: How Much Concurrency Should be Exposed in a UI Toolkit? Previous Topic   Next Topic Topic: New Python 3000 Video and Slides

Sponsored Links



Google
  Web Artima.com   

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