2012-02-03 7 views
4

나는 Java ME 퍼즐 게임을 썼다. 나는 코드를 작성했다. 즉, 앱이 시작할 때 시작하는 스레드가있다. 게임이 끝나면 무한 루프에서 실행되는 두 번째 스레드 인 메인 게임 루프가있다. 두 번째 스레드는 한 번에 다음과 같이 보입니다.자바 스레드를 정상적으로 인터럽트

public void run() { 
    init(); 
    while (shouldIRun) {    
     updateGameState(); 
     checkUserInput(); 
     updateGameScreen(getGraphics()); 
     this.flushGraphics();   
    } 
} 

멋진. 이 쓰레드는 실행하고, 죽이기 전까지 만 실행됩니다. 부울을 shouldIRun으로 설정하면, 정상적으로 종료됩니다.

하지만 나중에 나는 더 많은 것을 원한다는 것을 깨달았습니다. 게임은 퍼즐 게임이며 플레이어가 잘못된 동작을하고 붙어있을 가능성이 있습니다. 이러한 상황이 발생하면 양식을 실행하고 '재시작 수준'옵션을 선택할 수 있습니다. 그러면 restartLevel 플래그가 설정되고 무한 루프가 updateGameState() 메소드에 도달하면 레벨이 다시 시작됩니다. 하지만 이것은 약간의 도박을 느낀다. 나는 동시성 문제의 경우 메인 루프에서 사용되는 객체의 변수를 변경하고 싶지는 않지만, 아마도 편집증 적이기는하지만. 실제로 내가하고 싶었던 것을 깨달은 것은 매우 분명했습니다. 단지 을 잠깐 멈추고 무한 루프 스레드을 원하는대로 변경 한 다음 다시 시작합니다.

나는 다음과 같은 방법으로 이런 짓을했는지 :

public void run() { 
    init(); 
    while (shouldIRun) {    

     if (shouldIWait) { 
      iAmWaiting=true; 
      while (shouldIWait) { }; 
      iAmWaiting=false; 
     } 

     updateGameState(); 
     checkUserInput(); 
     updateGameScreen(getGraphics()); 
     this.flushGraphics(); 
    } 
} 

는 내가 생각하고하는 것은 다음과 같다. 이제 "기본"스레드에서이 두 번째 스레드를 "일시 중지"하려면 shouldIWait 변수를 true로 설정 한 다음 iAmWaiting 변수가 통보 될 때까지 반복하십시오. 이제 두 번째 스레드가 일시 중지되었음을 알게되고, 일시 중지 된 위치를 정확하게 알 수 있습니다. 실제로 "일시 중지됨"은 "당분간 무한 루프에 갇혀 있습니다"라는 의미입니다. 이제 몇 가지 필수 변수를 사용하여 레벨을 다시 시작하고 일반적으로 일을 정렬 한 다음 마지막으로 shouldIWait을 false로 설정하고 다시 해제합니다.

내 질문은 : 이것은 잘되고, 나를 위해,하지만 kludge의 박차기. 아마도 공통점 일 수있는 완전히 표준적인 방법이 있습니까? 스레드 주어진 지점에서 그리고 을 다시 시작할 때 제가 준비하고있을 때, 제가하고있는 것보다 낫습니다. 특히 나는 "무한 루프에 자바를 넣는 것"이 ​​아마도 영리한 일이 아니라고 생각합니다.

+0

당신은 적어도 잠시 동안 잠들기를 할 수 있습니다. (shouldIWait) –

+0

두 번째 스레드가 강제로 잠자기 상태가되어 주 스레드가 다시 작동하도록하려면? 확인 - 완료 :-) 그래도 여전히 kludge입니까? 나는 누군가가 "오, 그냥 t.pauseAtThisPointUntilISaySo()"또는 뭔가를 사용하길 기대하고있었습니다. –

+0

그래, 그게 답으로 제시하지 않은 이유입니다. =) 나에게 더 나은 사람이 있다고 생각하고있다. 기다리고있는 스레드에 대한 토론과 함께 이야기 할 것이지만, 필자는 제안한 것이 스핀 록 (spinlock)이라고 생각하며, 또한 효과적 일 수있는 항복 및 인터럽트를 사용할 수있는 방법이 있다고 생각한다. –

답변

1

일반적으로 Object.wait()Object.notify()을 사용합니다.

는 상황에 그것을 구현하는 몇 가지 방법이 있습니다 만, 여기에 간단한 예는 다음과 같습니다

Object monitor = new Object(); 
volatile boolean done = false, wait = false; 

/* Running on one thread: */ 
public void run() { 
    synchronized(monitor) { 
     while(!done) { 
      while(wait) { 
       monitor.wait(); 
      } 
      gameLogicAndStuff(); 
     } 
    } 
} 

/* Running on another thread: */ 
public void showResetForm() { 
    wait = true; 
    synchronized(monitor) { 
     actuallyShowResetForm(); 
     wait = false; 
     monitor.notifyAll(); 
    } 
} 
+0

나에게 뭔가 가르쳐 주었기 때문에 이것을 받아 들일 것입니다. 내가 그것을 구현할 수 있는지 여부는 또 다른 문제이다 :-)하지만 아마도, 결국, 결국. –

1

어쩌면 그냥 스레드를 죽이고 새로운 수준의 새로운 하나를 시작하는 것이 더 간단 할 것이다.

한 수준에서 다음 수준으로 이동해야하는 정보가있는 경우 먼저 몇 가지 일반 정보를 수집 한 다음 각 수준에 대해 스레드를 시작하도록 코드를 리팩터링 할 수 있습니다. (그리고 스레드를 시작하면 스레드 풀을 사용한다는 의미입니다.)

현재 바쁜 대기 중 무엇을하고 있는지 생각하는 것이 좋지 않습니다. Ben Flynn이 주석에서 언급했듯이, Thread.sleep (50)을 루핑하여 세미 바쁜 대기 상태로 만들 수 있습니다.

+0

이전 버전의 프로그램에서이 작업을 수행했지만 다양한 매개 변수가 전달되어야하고 특정 참조 루프가 발생할 가능성이있는 것으로 조금 걱정되었습니다. 그런 다음 위에서 제시 한 내용을 수행 할 수 있음을 깨달았습니다. 대신 그걸로 갔다. –

관련 문제