1

파일에서 레벨을로드 할 수있는 게임을 만들고 있습니다. 이 작업은 별도의 스레드에서 수행되는 반면 다른 모든 작업은 Event Dispatch Thread에서 수행됩니다.내 코드가 스레드로부터 안전하지 않은 이유는 무엇입니까?

정말 큰 테스트 파일에서로드하여 코드를 테스트 한 결과 레벨이로드되는 동안 이벤트 발송 스레드가 응답하지 않는 것으로 나타났습니다.

원인을 파악할 수없는 것 같습니다. 내가 코드에 두 개의 화살표를 추가 한

public class LevelSelectionWrapper extends GamePanel { 
    ... 
    private JList list; 
    private File[] files; 
    ... 
    //Lock object for synchronization 
    private Object lock = new Object(); 
    //Runnable for loading levels from files on a separate thread 
    private Runnable loader = new Runnable() { 
     @Override 
     public void run() { 
      synchronized(lock) { 
       //Load levels from files 
       List<Level> levels = LevelLoader.load(files); // <------------- 
       ... 
       SwingUtilities.invokeLater(new ListUpdater()); 
      } 
     } 
    }; 
    ... 
    private void createOpenFileButton(Container container) { 
     final JFileChooser fc = ... 
     ... 
     //Create open button 
     JButton openButton = new JButton("Open file"); 
     openButton.setFocusable(false); 
     openButton.addActionListener(new ActionListener() { 
      @Override 
      public void actionPerformed(ActionEvent e) { 
       int returnVal = fc.showOpenDialog(LevelSelectionWrapper.this); 
       if(returnVal == JFileChooser.APPROVE_OPTION) { 
        synchronized(lock) { files = fc.getSelectedFiles(); } 
        //Load files on separate thread 
        new Thread(loader).start(); // <------------- 
       } 
      } 
     }); 
     container.add(openButton); 
    } 
} 

: 여기에 내 코드의 일부이다

  • 첫 번째는 시간이 소요 방법 (파일이 정말 큰 경우)입니다. 때로는이 코드가 실행되는 동안 Event Dispatch Thread가 응답하지 않습니다.
  • 마지막 하나는 실행 파일이 호출되는 곳입니다.
+1

이 문맥에서'syncronized (lock) '이란 무엇입니까? 나에게 syncronization의 나쁜/불필요한 사용처럼 보인다. 예를 들어 로컬로 파일 목록을 가져 와서 복사본을 만들고 로더에 복사를 전달하는 것보다 나중에 잠글 수있는 공유 개체를 사용하는 것이 좋습니다. 내가 오해하고 있다면 그게 목적이 될거야, 아마도 너는 그것에 대해 정교 할 수있을거야. – dimo414

+0

이 앱의 EDT 만 응답하지 않나요, 아니면 시스템의 나머지 부분입니까? –

+0

@Ralf : EDT와 작업자 스레드라는 두 개의 스레드 만 사용하고 있습니다. EDT는 작업자 스레드가 완료 될 때까지 응답하지 않습니다. –

답변

3

해당 lock 개체 (및 관련 종속성)를 제거하는 것이 좋습니다. actionPerformed() 안에있는 파일 목록을 가져 와서 복사본을 만들어 실행 파일로 전달하십시오. 현재 스레드처럼 불필요하게 공유되는 인스턴스 변수 인 files을 사용하지 마십시오.

synchronized 블록이 가장 가능성이 큰 블록입니다. 그래도 문제가 해결되지 않으면 어떤 전화가 너무 오랫동안 걸리는지 확인하기 위해 차단하는 부분을 System.out.println() 번으로 추가하는 것이 좋습니다.

직접 새 스레드를 구성하는 대신 SwingWorkers을 사용해보십시오. 그러면 EDT에서 스레드 시작 시간을 몇 사이클 줄일 수 있습니다.

+1

감사합니다.이 답변은 큰 도움이되었습니다. SwingWorkers를 사용하기로 결정했는데, 지금까지는 Event Dispatch Thread가 응답하지 않았습니다. 또한, 자물쇠가 없기 때문에, 이미 레벨 로딩이있는 동안 다른 레벨을로드 할 수 있습니다. –

+0

니스! 'synchronized' 블록은 유용한 도구이지만 동시성을 처리하기위한 더 깨끗하고 우아한 솔루션이 많이 있습니다. 가능한 한 데이터를 한 번에 하나의 스레드로 제한하십시오. – dimo414