2011-04-07 2 views
0

Java로 동시 프로그래밍을해야하기 때문에 오랜 시간이 걸렸습니다. (실제로 동시 프로그래밍 대학 수업이었습니다. 꽤 기본적인 문제로 보입니다. 내가 UI 컨트롤에 대한 표준 JDK를 사용하지 않는 때문에 아래의 예제 코드는 좀 이상하게 보일 수도 있지만, 이렇게되면 :자바 : 제대로 작동하지 않을 때까지 대기/통보하지 못합니다 - 동시성 문제

//class Screen 
public class Screen{ 
    private Frame rootContainer; 

    public Screen(Frame rootContainer){ 
     this.rootContainer = rootContainer; 
     this.createGui(); 
    } 

    private void createGui(){ 
     Button btn = new Button("Call"); 
     btn.setBounds(20, 20, 100, 20); 
     rootContainer.add(btn); 
     btn.addActionListener(new ActionListener() { 

      public void actionPerformed(ActionEvent e) { 
       ConcurrentDialog cr = createDialog(); 
       cr.start(); 
       //Suposedly only to be called after the Exit button in the dialog is clicked 
       ((Button)e.getSource()).setLabel("Called"); 
       ((Button)e.getSource()).repaint(); 
      } 
     }); 
    } 

    private ConcurrentDialog createDialog(){ 
     return new ConcurrentDialog(rootContainer, this); 
    } 
} 

//Class ConcurrentDialog 
public class ConcurrentDialog extends Thread { 
    private Frame rootContainer; 
    private Screen screen; 

    public ConcurrentDialog(Frame rootContainer, Screen screen){ 
     this.rootContainer = rootContainer; 
     this.screen = screen; 
    } 

    public void run(){ 
     createDialog(); 
     synchronized(screen){ 
      try { 
       screen.wait(); 
      } catch (InterruptedException e1) { 
       e1.printStackTrace(); 
      } 
     } 
    } 

    private void createDialog(){ 
     Dialog dialog = new Dialog(rootContainer, true); 
     dialog.setBounds(20, 20, 110, 35); 
     Button btn = new Button("Exit"); 
     btn.setBounds(5, 5, 100, 20); 

     btn.addActionListener(new ActionListener() { 

      public void actionPerformed(ActionEvent e) { 
       Button source = (Button)e.getSource(); 
       Dialog dialog = (Dialog)source.getParent(); 

       synchronized(screen){ 
        screen.notify(); 
       } 

       dialog.dispose(); 
       dialog.getOwner().remove(dialog); 
       dialog = null; 
      } 
     }); 

     dialog.add(btn); 
     dialog.show(); 
    } 
} 

사람이 요청하기 전에, 그래, 난에 (모달 대화 상자를 구현하기 위해 노력하고있어 사실, ConcurrentDialog의 이름을 ModalDialog로 변경해야합니다.) 전에 말했듯이, 나는 스윙을 사용하지 않고있다. (왜냐하면 내가 할 수 없기 때문이다 ... 임베디드 VM은 UI에 관해서는 플랫폼에 따라 다르다. 내 경우에 해당한다.) 그리고이 특정 라이브러리에는 모달 대화 상자가 없다. (JOptionPane.showMessageDialog가 나를 사랑한다는 것을 의미하지 않는다) 그래서 나는 처음부터 하나를 만들고있다.

어쨌든 여기에 문제가 있습니다. wait() 메서드가 ((Button) e.getSource()). setLabel ("Called")보다 훨씬 나중에 실행되는 것 같습니다. 내가 찾은 해결 방법은 공공 액세스 할 수있는 글로벌 속성으로 btn을이의 run() 메소드 리팩토링 설정입니다 :

public void run(){ 
    createDialog(); 
    synchronized(screen){ 
     try { 
      screen.wait(); 
     } catch (InterruptedException e1) { 
      e1.printStackTrace(); 
     } 
    } 
    screen.getBtn().setLabel("Called"); 
    screen.getBtn().repaint(); 
} 

그것은이 방식으로 작동하지만, 내 "현실 세계"시나리오를,이 구현은 원인이 커플 링에 관해서는 꽤 엉망입니다. 어떤 포인터?

답변

1

cr.start()가 즉시 반환됩니다.

원하는 것은 cr.start() 다음에 대기 (화면)를 넣고 run() 메서드에서 대기 (화면)를 제거하는 것입니다.

이렇게하면 대화 상자가 표시되고 종료됩니다. 대화 상자가 닫히면 화면에 알림이 표시되고 createGui(). actionPerformed()가 활성화됩니다.

+0

이전에 시도했지만 대화 상자가 응답하지 않게되었습니다. 나는 cr.start()에서 생성 된 스레드가 주 스레드에서 wait()를 호출하기 전에 실행을 끝내고 다른 스레드가 notify()를 호출하는 동안 기다리는 단 하나의 스레드를 발생시키기 때문에 결과가 있다고 가정합니다. – makoshichi

+0

스레드 내부에서 synchronized() 블록을 없애면 괜찮을 것입니다. – iluxa

0

스윙/awt와 함께 여러 스레드를 사용할 수 없으며 GUI를 실행중인 스레드에서 "대기"할 수 없거나 작동을 멈 춥니 다. gui를 포함하는 비동기 작업을 수행하는 방법은 별도의 스레드를 생성 한 다음 (또는 수행 할 때마다) 해당 스레드가 GUI를 "업데이트"해야 할 때마다 SwingUtilities.invokeLater()를 사용하게하는 것입니다.

관련 문제