I got stuck overhauling a badly implemented Swing application, not so long ago. Seems I end up doing desktop GUI applications every several years. Been doing this since pre-Windows days, so long ago learned the rule that long-running tasks should never be performed on the UI thread (or the equivalent). Have also seen (many times!) that most programmers are not aware of the rule and the underlying reason. The Swing application (to my complete lack of surprise) performed pretty much everything on the UI thread.
Refactoring an existing application to move long-running tasks off to a background queue, is not easy. The flow of control that leads to disk, network, or database operations can be rather indirect. You could have long-running operations still performed on the UI thread (via an indirect path) of which you are not aware. Even for an application written from scratch with full knowledge of the relevant principles, there is some chance an indirect control path might unexpectedly place a potentially long-running task on the UI thread.
You could put tests in various places to check that (say) disk and network operations are not performed on the UI thread, but that adds complexity and expense to existing code, is prone to error, and only catches problems after the fact. Not exactly an elegant or minimal solution.
What we really want is an efficient solution that makes the usual errors impossible. You want a file, network, or database operation on the UI thread to fail to get past the compiler - or at the very least to fail on the first invocation.
The world of server-side Java web applications offers a solution. Java web application servers (like Jetty or Tomcat) use custom class loaders to isolate distinct web applications. Classes loaded into one web application are completely unknown (and unshared) with other web applications hosted on the same application server.
The same notion - with a twist - could be applied to desktop GUI applications. The UI thread could use a class loader that knew about Swing (or the equivalent), and knew nothing about classes that did file, network, or database operations. The non-UI threads would not have access to any of the GUI (Swing or the like) related classes.
The project setup would be a little more complicated, but any errors could be caught at compile-time, without adding any additional complexity or runtime expense to existing classes.
This seems to imply a rather significant of reorganization of the stock Java classes.
Ran across this article, that takes a less interesting run at a similar problem.
Should Java Assert that Network I/O Can’t Occur on the UI Thread? Doing network I/O on the user interface (UI) thread is bad. Most developers know that and can tell you why; unfortunately, it’s still done. At this year’s JavaOne, one of the keynote JavaFX demos bombed because the network was slow, something that would be forgivable had the entire application’s UI not frozen, which required it to be restarted, only to trip up again a few minutes later.
I believe to notion of using class loaders to completely isolate the class name-space is a more efficient solution.