# Java Basics

# `main` and the GUI Event Dispatch Thread

## Threads in a GUI system

There are at least three threads that are typically used in a GUI application.

1. Initial thread - This is the thread that start main. Stops when main returns.
2. Event Dispatch Thread (EDT) - Initializes and runs the GUI, and calls listeners.
3. Worker threads - These should be started for any slow listener.

## 1. Initial thread

This is the thread that the main program starts on. The main program may do various intializations (eg, intializing the model), but the the last thing that is typically done in main on this thread is to start the EDT, Event Dispatch Thread. The initial thread is terminated when main finishes, and the only thread that continues at this point is the EDT.

## 2. Event Dispatch Thread (EDT)

Initialization on the EDT. The GUI should be initialized on the EDT, although for simple programs this is generally not necessary, and often not done. Early versions of Java didn't require it, but later versions of Java require GUI initialization on the EDT to avoid certain problems.

My examples generally don't initialize on the EDT, and I've got a nice long list of excuses: this is a consequence of history (some are old), laziness, and attempts to keep the very simple programs very simple. But because it might cause a problem, the examples will be changed.

setVisible(true) side-effect. Even if you didn't initialize the GUI on the EDT, a side-effect of calling `setVisible(true)` is to start the EDT thread, which continues to run and monitor the GUI.

Problem: Listeners called on EDT. The source of serious problems revolves around listeners. Listeners are called on the EDT, but while the listener is busy, the GUI is frozen because the thread which runs the GUI, the EDT, is busy. The solution is to run long-running listener actions on a worker thread.

## 3. Worker threads for long actions

When a listener is called (eg, `actionPerformed`), it's called on the Event Dispatch Thread, the same thread that runs the GUI. While the listener is being executed, the GUI is frozen! If the action is short (eg, less than 50 milliseconds), you can simply do it and return from the listener, and the user will never know that the GUI was not active for a fraction of a second. If you're doing something longer, eg, processing a lot of data or interacting over a network, you should start up another thread to do the work.

Coordination headaches. Coordinating threads is not trivial; it's easy to get into race or deadlock situations, and communicating between threads can be difficult. The Java 6 solution is to use `SwingWorker`. There have been earlier, incompatible, versions of SwingWorker, as well as other packages, such as Foxtrot, which to ease the pain of working with multiple threads. JSR 296 will probably also provide other solutions.

[Where I stopped writing about SwingWorker -- needs more thought]

## SwingWorker -- what it can do

- Must define `doInBackground()` to run a long task on another thread.
- Return a value to the original "caller".
- Will call a method on the EDT when it is finished (eg, to display results).
- Can be cancelled from another thread.
- Can be asked if it is finished or cancelled.
- Can provide intermediate results (eg, for a progress bar).

## Example: GUI construction on EDT

For small programs there are no problems, but for building more complex GUIs, the initialization may require use of the EDT. To call the GUI constructor on the EDT, use code like the following.

      1
      2
      3
      4
      5
      6
      7
      8
      9
     10
     11
     12
     13
     14
     15
     16
     17
     18
     19
     20
     21
     22
     23
     24
     25
     26
     27
     28
     29
    // File   : gui-tutorial/tw2/TinyWindow2T.java
    // Purpose: Based on TinyWindow2, this shows how to initialize
    //          the construction of a GUI on the EDT thread.
    //          This is the recommended way, but for simple programs
    //          is typically omitted.
    // Author : Fred Swartz, 2007-01-15, Placed in public domain.

    import javax.swing.*;

    ////////////////////////////////////////////////////// class TinyWindow2
    class TinyWindow2T extends JFrame {

        //====================================================== method main
        public static void main(String[] args) {
            SwingUtilities.invokeLater(new Runnable() {  //Note 1
                public void run() {
                    TinyWindow2T window = new TinyWindow2T();
                    window.setVisible(true);
                }
            });
        }

        //====================================================== constructor
        public TinyWindow2T() {
            //... Set window characteristics
            setTitle("Tiny Window using JFrame Subclass");
            setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        }
    }

### Notes

1. This will call the run() method from the EDT.