2013-02-12 4 views
1
public static void moveTo(Coordinate destination) { 

    changeState(State.NAVIGATION); 
    controlPnl.addRemote(Remote.createRemote(remoteType.NAVIGATION)); 

    dmc.moveTo(destination); 

    changeState(State.IMMEDIATE); 
    controlPnl.addRemote(Remote.createRemote(remoteType.IMMEDIATE)); 
} 

이 코드에서 addRemote 메소드는 controlPnl GUI를 새 버튼으로 업데이트합니다. dmc.moveTo 메쏘드는 최대 두 개의 Thread.sleep 호출을 가지고 있으며 controlPnl GUI가 업데이트되기 전에 호출되고 있다고 생각합니다. dmc.moveTo를 호출 한 후에 GUI를 다시 변경하고 moveTo가 실행을 완료 할 때까지 controlPnl이 업데이트를 완료하지 않은 후에 두 메서드 호출을 주석 처리했습니다. 필요한 것은 moveTo 메소드가 실행되기 전에 GUI가 업데이트를 끝내고 스레드가 잠자기 상태가되도록하는 것입니다. Java 6에서이 작업을 수행 할 수있는 방법이 있습니까?GUI 업데이트 전 대기 스레드 (Java 6)

문제가있는 경우 moveTo 메서드는 LEGO Mindstorm 로봇을 사용자가 정의한 경로의 지정된 지점으로 이동합니다. 업데이트되는 GUI는 사용자가 네비 게이팅하는 동안 로봇을 제어 할 수 있도록 Swing 구성 요소 (JButton 및 JRadioButtons)를 제공합니다. addRemote 메서드는 사용자가 사용할 수 있도록 Swing 구성 요소 집합을 변경하고 moveTo 메서드는 실제 이동을 실행하기 위해 로봇에 명령을 보냅니다 (모터의 이동, 정확한 시간 동안의 잠자기, 모터에 알리기). 멈춤). 상태 머신 패턴을 사용하고 있는데이 메서드는 UI에서 이벤트를 처리하는 컨트롤러의 일부입니다.

답변

0

단일 GUI 스레드가 있습니다. 그것을 사용하여 다른 것을 부르지 마십시오. 그렇게 할 경우 GUI에서 다른 작업이 완료되기 전에 완료해야합니다.

최소한 새 스레드를 시작하여 dmc.moveTo(destination)을 수행하고 싶습니다. 아마도이 작업을 수행하는 유일한 장소는 아니며 아마도 Executor이 이러한 작업을 수행하기를 원할 것입니다. (정적 방법을 사용하고 특히 이후) 코드에 대한 자세한 내용을 모른 채

난 당신이 될 것 Executor하지만 Thread를 사용하는 간단한 예제를 설정하려는 것입니다 방법에 대해 언급 할 수 없습니다

public static void moveTo(final Coordinate destination) { 

    changeState(State.NAVIGATION); 
    controlPnl.addRemote(Remote.createRemote(remoteType.NAVIGATION)); 

    new Thread(new Runnable() { 
        public void run() { 
         dmc.moveTo(destination); 
         changeState(State.IMMEDIATE); 
         controlPnl.addRemote(Remote.createRemote(remoteType.IMMEDIATE)); 
        } 
       }).start(); 
} 

이렇게하면 moveTo()을 수행하는 (익명) Runnable을 실행하는 새 Thread이 생성됩니다. 이 작업을 수행 할 준비가 된 Executor을 갖는 것보다 훨씬 효율적이지 않습니다. 매번 새로운 Thread을 생성해야합니다. 그러나 그것이 당신이 필요로하는 성능 측면에서 쟁점이 아니라면 그것은 완벽합니다. 또한 익명의 내부 클래스 내부에서 destination을 참조하기 때문에 메서드에 전달 될 때 final으로 선언되어야합니다.

+0

당신이 그랬던 것처럼 나는 그것을 구현 (오히려 실행 가능한-에서-A-의 Runnable 익명 클래스를 사용하는 것보다 별도의 방법으로이 물건을 인수 분해에 더 많은 의미가 있습니다)뿐만 아니라,라고 나는 스레드에 가입 시작한 후. 나는 또한 Swing 호출을 SwingUtilities로 싸웠다.invokeLater'를 호출하면 moveTo 스레드가 실행을 마친 후에 GUI가 깜박입니다.하지만 GUI가 moveTo 메소드가 실행을 끝내고 NAVIGATION 뷰로 업데이트되고 즉시 IMMEDIATE 뷰로 돌아갈 때까지는 업데이트되지 않은 상태로 남아 있습니다. 도와 주셔서 감사합니다. 나는 지금있을 곳이 없다면 코드에 대한 자세한 내용을 추가 할 것입니다. – Nelson

+0

@ user2065144 - 스레드에서'join()'을 호출하지 마십시오. GUI 스레드가 완료 될 때까지 기다릴 것입니다. 원래의 문제로 바로 돌아갑니다. 일단'run()'이 끝나면'Thread'가 끝나고 가비지 컬렉터가 될 것입니다. . –

+0

네, 감사합니다. 나는 당신이 호출 한 스레드가 완료 될 때까지 조인이 현재 스레드의 실행을 멈추었다 고 생각 했으므로 코드를 IMMEDIATE로 다시 전환하지 못하도록했습니다. 그러나 이제는 조인을 제거했습니다. 'change state'와'add remote' 메쏘드를 run 메쏘드에 넣으십시오. 당신의 도움을 주셔서 대단히 감사합니다. – Nelson

0

moveTo은 시간이 오래 걸리기 때문에 메인 이벤트 처리 스레드에서 실행하지 마십시오. 대신 moveTo을 GUI로 업데이트하고 별도의 스레드에서 실제 이동을 시작하십시오. 이동이 완료되면 SwingUtilities.invokeLater을 사용하여 두 번째 GUI 업데이트 세트를 수행하십시오.

private static ExecutorService executor = Executors.newCachedThreadPool(); 

public static void moveTo(final Coordinate destination) { 

    changeState(State.NAVIGATION); 
    controlPnl.addRemote(Remote.createRemote(remoteType.NAVIGATION)); 

    executor.execute(new Runnable() { 
     public void run() { 
     dmc.moveTo(destination); 
     SwingUtilities.invokeLater(new Runnable() { 
      public void run() { 
      changeState(State.IMMEDIATE); 
      controlPnl.addRemote(Remote.createRemote(remoteType.IMMEDIATE)); 
      } 
     }); 
     } 
    }); 
} 

이 방법 moveTo은 GUI 업데이트의 초기 설정을 수행 한 후 응답 GUI를 유지하기 위해 이벤트 루프를 자유롭게 즉시 반환하지만 dmc.moveTo가 완료 될 때까지 두 번째 changeState이 지연됩니다.

+0

고마워, 거의 끝내기는했지만, 이제는 invokeLater 메소드가 addRemote 메소드 내에서 호출되었다. – Nelson