2007년 10월 8일 월요일

Java Thread & Swing

Java 에서 일반적인 방식으로 GUI 를 다루는것은 안전하다. 그러나 GUI 에 영향을 주는 명령을 수행하는 thread 를 사용하거나 표준적인 event 가 아닌 다른 event 에 응답해서 이미 스크린상에 보여지고 있는 GUI 를 조작할 경우에는 다음 규칙을 지켜야 한다.

규칙: Swing component 가 realized 되고 있다면 그 component 에 영향을 주거나 의존하는 모든 코드들은 event-dispatching thread 안에서 실행 되어야 한다. (일부 thread-safe 한 API 도 있다)

realized 란. 다음 세 명령어에 의해 이루어 진다.
[ setVisible(true), show, pack ]

예외1. repaint(), revalidate() thread 에서 안전하다.
예외2. Listener리스트는 수정은 thread 에서 안전하다.


Event-Dispatching Thread 에서 코드를 실행하는 방법
GUI 초기화가 이루어진 이후의 대부분의 작업은 자동적으로 event-dispatching thread 에서 일어난다. 일단 GUI가 realized 되면, 버튼을 누르거나 마우스를 클릭하는 등의 이벤트가 프로그램의 대부분을 구성하게 되는데, 이러한 이벤트들은 항상 event-dispatching thread 에서 다루어진다.

그러나 통신 프로그램이나 thread 방식의 프로그램은 GUI가 가시화 된 이후에 non-event-driven GUI 작업을 수행할 때도 있다.

SwingUtilities 클래스는 event-dispatching thread 안에서 코드를 실행하도록 돕는 두개의 메소드를 제공한다.


invokeLater
이 메소드는 일부 코드가 event-dispatching thread 에서 실행될것을 요청한다. 이 메소드의 결과는 코드가 실행되기를 기다리지 않고 즉시 반환된다. 보류중인 모든 AWT 이벤트가 처리된 뒤에 실행된다.

Runnable InvokeTest = new Runnable() {
    public void run() {
        System.out.println("Thread " + Thread.currentThread());
    }
};
SwingUtilities.invokeLater(InvokeTest);


invokeAndWait
invodeLater 와 비슷한 기능을 한다. 다른점이라면 이 메소드는 코드가 실행되는동안 기다린다는 것이다. 이 메소드는 EventDispatchThread로 부터 호출하면 안된다. 이 메소드보다 invokeLater 메소드를 추천한다.

Runnable InvokeTest = new Runnable() {
    public void run() {
        System.out.println("Thread " + Thread.currentThread());
    }
};
try {
    SwingUtilities.invokeAndWait(InvokeTest);
} catch (Exception e) {
    e.printStackTrace();
}

댓글 없음: