Java Swing 기초 - Event Dispatch Thread

by Vincent Lee,

Swing(정확하게는 AWT)의 GUI 이벤트는 event dispatch thread라는 특수한 스레드에서 처리되며, Swing 객체의 메소드는 대부분 thread-safe하지 않기 때문에1 모든 Swing 이벤트 핸들링과 Swing 프레임웍을 다루는 코드 대부분은 event dispatch thread 상에서 실행되어야 한다.2 따라서 일반적인 Swing 애플리케이션의 main 메소드는 GUI를 구동하는 Runnable 객체를 생성하여, event dispatch thread에서 실행되도록 요청(invoke)하는 코드가 된다. Swing의 event dispatch thread에 이런 실행을 요청하는 방법은 SwingUtilities 클래스의 invokeLater 메소드3invokeAndWait 메소드4가 있으며 실제 예는 다음과 같다.

import javax.swing.*;

public class SwingExample implements Runnable {
    private void createAndShowGUI() {
        JFrame f = new JFrame("Hello, World!");
        f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        f.setVisible(true);
    }

    @Override
    public void run() {
        createAndShowGUI();
    }

    public static void main(String[] args) {
        SwingUtilities.invokeLater(new SwingExample());
    }
}

아래와 같이 애플리케이션 클래스가 Runnable 인터페이스를 구현(implements)하지 않고 익명 클래스(anonymous classes)를 사용하는 형태일 수도 있다. 중요한 것은 event dispatch thread 상에서 Swing 코드가 시작하고 실행되는 것이다.

public class SwingExample {
    public static void main(String[] args) {
        SwingUtilities.invokeLater(new Runnable() {
            public void run() {
                createAndShowGUI();
            }
        });
    }
}

invokeLater 메소드는 Runnable 객체를 event dispatch thread가 대기 중인 AWT 이벤트를 모두 처리한 후 실행되도록 큐(queue)한 후 곧바로 리턴한다(asynchronously). invokeAndWait 메소드는 대기 중인 AWT 이벤트를 모두 처리하고 Runnable 객체를 실행한 후 리턴한다(synchronously). invokeLater 메소드와는 다르게 invokeAndWait 메소드는 event dispatch thread 상에서 호출하면 안 된다. 일반 스레드가 모두 종료되어야 JVM이 종료되기 때문에, 위 프로그램은 Swing(AWT) GUI가 완전히 실행을 마친 후 종료될 것이다.

References

1 Swing and thread safety (Wikipedia)

2 The Event Dispatch Thread

3 invokeLater method

4 invokeAndWait method