문제

최근에 작업 한 프로젝트에 대해 많은 질문을 해왔습니다. 여기에 내가있는 시나리오가 있으며 올바른 방향으로 도움이나 지적이 많이 도움이 될 것입니다 ... 많은 도움이 될 것입니다 ...

이것은 서버 및 여러 클라이언트로 구축 된 네트워크 프로그램입니다. 각 클라이언트에는 서버에서 전송 된 명령에 따라 행동 해야하는 GUI가 있습니다. 각 클라이언트는 호출 된 클래스 내에 래핑됩니다 Player. 이것 Player GUI가 있습니다 (확장 JFrame) 및 기본 메소드 및 서버에는 기본 메소드 만 있습니다 (GUI 없음). 처음에는이 클래스가 다음과 같은 메인 스레드에서 만들어졌습니다.

EventQueue.invokeLater(new Runnable()
{
    public void run()
    {
        new Player().setVisible(true);
    }
 });

나는 전체가 Player EDT에서 수업이 실행되었습니다. 따라서 서버에서 명령을 기다리면 해당 명령이 전송 될 때까지 전체 GUI가 잠그고 적절한 작업이 실행됩니다. 당신이 상상할 수 있듯이, 이것은 끔찍한 디자인이며, 당신이 무언가를 확인하고 싶을 때마다 GUI가 여전히 그대로 유지되도록 미친 일을 찾아야 할 때마다 코딩 환경의 진정한 고통으로 판명되었습니다.

분명히, 나는 별도의 스레드에서 서버의 명령을 확인하고 EDT에서 GUI 구성 요소를 실행해야합니다. 두 번째 구현에는 두 개의 클래스가있었습니다. 하나는 GUI와 하나는 Player. 아이디어는 Player GUI를 보유한 변수가있어서 GUI에 액세스 할 수있었습니다. Player 클래스, 이와 같은 것 :

class Player
{
    public GUI gui;

    ...

    // And then start this gui inside of the EDT.
    EventQueue.invokeLater(new Runnable()
    {
         public void run()
         {
              this.gui = new GUI().setVisible(true);
         }
    }

이것은 작동하지 않습니다 this 새로운 내부 Runnable 객체를 말합니다 Runnable 대상이 아닙니다 Player.

내가 어떻게 통신 할 수 있습니까? Player EDT 스레드의 한 스레드와 해당 GUI 클래스에서 클래스?

다른 팁

당신의 문제를 처리합니다 this 포인터, 당신은 다음을 작성해야합니다.

class Player
{
    public GUI gui;

    ...

    // And then start this gui inside of the EDT.
    EventQueue.invokeLater(new Runnable()
    {
         public void run()
         {
              Playser.this.gui = new GUI().setVisible(true);
         }
    }
}

Boris Pavlović는 구문을받습니다 (실제로는 this.), 그러나 여전히 코드는 의미가 없습니다. 그만큼 gui 필드는 이후 언젠가 초기화됩니다 Runnable 이벤트는 대기열이므로 플레이어 스레드가 사용하는 것은 안전하지 않습니다.

당신은 구성 할 수 있습니다 Player EDT에서 (그러나 EDT에서 네트워크 작업을 수행). 또는 GUI를 청취자 (관찰자)로 등록하십시오. Player. invokeAndWait 효과가 있지만 종종 가끔 멍청한 교착 상태로 이어지기 때문에 위험합니다.

당신은 이것을 시도 할 수 있습니다 :

클래스 플레이어 {public gui gui;

...

// And then start this gui inside of the EDT.
EventQueue.invokeLater(new Runnable()
{
     public void run()
     {
          Player.this.gui = new GUI().setVisible(true);
     }
}

"전체 플레이어 클래스가 EDT에서 실행되고 있음을 깨달을 때까지"

생성자는 EDT에서 발생하지만이 클래스에서 호출 된 메소드는 그렇지 않을 수 있습니다.

원래 의도 한대로 플레이어 GUI를 구성해야합니다.

 EventQueue.invokeLater(new Runnable() 
 {
    public void run()
    {
        new Player().setVisible(true);
    }
 });

그러나 플레이어는 생성자에서 별도의 스레드를 시작할 수 있습니다 (개인적으로 플레이어 간의 연결을 공유합니다).

물론, 서버의 콜백 메소드는 가시 구성 요소를 수정할 때 invokelater ()를 사용해야합니다.

익명의 내부 클래스를 사용하는 대신, 클래스를 구현 가능한 클래스를 선언하고 GUI 인스턴스를 인수로 취하는 생성자가있는 이유는 무엇입니까?

또한 GUI 클래스가 스레드 안전하지 않은 경우 메시지 대기열을 사용하여 EDT 및 메인 스레드간에 통신하는 것을 고려하십시오.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top