2014-05-11 3 views
0

그러니까 기본적으로 내 응용 프로그램의 GUI를 업데이트됩니다, 그래서 정적 메서드자바는 통지

무효 javax.swing.SwingUtilities.invokeLater (의 Runnable doRun)

를 사용

하지만 초기화 코드를 실행 파일과 논리 코드 외부에 넣고 싶습니다. 그러나 invokeLater 메서드를 호출하면 invokeLater 메서드가 호출 된 직후에 내 주 스레드가 내 논리 코드를 호출하려고하기 때문에 내 주 스레드와 AWT 스레드가 경쟁 상태가되지만 JFrame 이후 (내 case)가 아직 초기화되지 않았으므로 내 메인 스레드가 레이스에서 이기고 예외가 발생합니다.

Event-Dispatching 스레드가 실행 가능한 runnable을 기다렸다가 초기화 코드를 초기화 할 때 runnable에서 알릴 수 있다고 생각했습니다. 그러나 어떤 이유로 든 아래 코드 (약식)가 작동하지 않습니다.

경량 응용 프로그램의 경우 실행 가능 파일이 경쟁 조건에서 이기기 때문에 예외가 발생하지 않지만 응용 프로그램에서 초기화 코드가 길어집니다.

SSCCE : 사전에

public class SSCCE { 
    private static JFrame frame; 
    public static void main(String[] args) { 
     Runnable r = new Runnable() { 
      public void run() { 
       synchronized (this) { 
        frame = new JFrame(); 
        frame.setTitle("JFrame"); 
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
        frame.setLocationRelativeTo(null); 
        this.notifyAll(); 
        System.out.println("Notified all"); 
       } 
      } 
     }; 
     synchronized (r) { 
      try { 
       System.out.println("Waiting"); // EDIT this line was after the wait method, and therefore it didn't execute. 
       r.wait(); 
      } catch (InterruptedException e) { 
       throw new RuntimeException("Unexpected disruption whilst waiting for the \"Event-Dispatching thread\".",e); 
      } 
     } 
     SwingUtilities.invokeLater(r); 
     frame.setVisible(true); 
     frame.getContentPane().add(new JLabel("Hello World!")); 
     frame.pack(); 
    } 
} 

감사합니다!

+1

미안하지만이 동기는 무엇입니까? –

+1

모든 Swing GUI 코드는 Event Dispatch Thread에서 실행되어야합니다. invokeLater()를 사용하는 것은 EDT에 코드를 추가하는 것입니다. Runabble을 동기화 할 필요가 없습니다. 나는 정말로 당신이 복잡한 것을 생각합니다. EDT에 모든 코드를 입력하십시오.장기 실행 태스크가있는 경우, GUI가 이미 작성되고 가시화 된 후 init 코드 내에서 해당 태스크를 호출 할 수 있습니다. – camickr

+0

@HovercraftFullOfEels GUI가 업데이트 될 응용 프로그램을 만들고 invokeLater가 AWT 이벤트 디스패치 스레드에서 주 스레드를 비동기 적으로 실행해야하지만 이후 JFrame에 직접 액세스하려고하므로 예외가 발생합니다. 아직 초기화되지 않았기 때문에 – Linus

답변

1

귀하의 실수는 매우 간단합니다 : 당신이 요구하고있다 (이 일을하면 잘, 당신은했다) 당신이 결과를 wait하려고하는 후 invokeLater:

synchronized (r) { 
    try { 
    … 
    r.wait(); // <- here you are waiting 
    } catch (InterruptedException e) { 
    … 
    } 
} 
SwingUtilities.invokeLater(r); // <- never reached, you are waiting above 

그래서 명백한 수정 호출하는 것입니다 SwingUtilities.invokeLater(r);첫 번째wait이후입니다.


그러나 오히려 사용되지는 EDT에 Runnable을 예약하고 완료를 기다리지의 작업을 수행하는 방법 SwingUtilities.invokeAndWait(r);있다. 따라서 사용자가 직접 동기화 및 알림을 프로그래밍 할 필요가 없습니다.


그러나 주요 방법에 선 당신이 invokeLater이 UI를 조작하고, 따라서 마찬가지로, 그렇지 않으면 당신은 아직도 여전히 스윙의 스레딩 정책을 위반하는 JFrame의 건설처럼 EDT 내에 위치해야 다음과 같은 점에 유의 경주 조건을 얻을 수 있습니다.

귀하의 main 스레드가 EDT와 동시에 작업을 수행 할 수 있으며 원하는 경우 UI 구성을 기다릴 수 있습니다. 하지만 이 아니고은 UI 자체를 조작해야합니다. 이러한 조작은 JFrame을 조작하는 것이 "논리 코드"에 속하지 않으므로 "논리 코드 외부"를 갖고 싶다는 진술과 모순됩니다.