2010-06-30 6 views
9

내 상황은 다음과 같습니다. 내 게임의 활동은 게임 로직 및 렌더링을위한 스레드가있는 사용자 정의 surfaceView로 구성됩니다. 이 아키텍처는 Google 웹 사이트의 LunarLander 데모와 비슷합니다. "스레드가 이미 시작되었습니다"활동을 재개 할 때

활동이는 서피스 뷰 SurfaceView를 생성하고이 메소드를 호출 시작

:

@Override 
    public void surfaceCreated(SurfaceHolder holder) 
    { 
     renderThread.start(); 
    } 

내가 surfaceDestroyed를 호출하는 게임의 onPause() 메소드가 호출을 종료하려면 홈 버튼을 누르면(). SurfaceDestroyed에서 나는 전화로 게임 스레드를 멈춘다 :

@Override 
    public void surfaceDestroyed(SurfaceHolder holder) 
    { 
     synchronized(holder) 
     { 
      renderThread.stop(); 
     } 
    }  

애플 리케이션은 백그라운드로 잘 간다. 그런 다음 아이콘을 눌러 앱을 다시 실행하면 화면에 "강제 종료"팝업과 함께 로그에 "스레드가 이미 시작되었습니다"라는 메시지가 표시됩니다. 이 메시지는 렌더 스레드에서 start()를 호출 할 때 활동이 "surfaceCreated"메소드로 들어갈 때 발생합니다.

이제 몇 시간 동안 살펴 봤는데 이유가 무엇인지 알 수 없습니다. 응용 프로그램을 닫을 때 내 스레드가 중지되어 내가 이미 시작되었다고 말하는 이유를 이해할 수 없다고 생각합니다.

답변

8

이러한 방법은 자신이 생각하는대로하지 않습니다. API doc :

두 번 이상 스레드를 시작하는 것은 결코 불가능합니다.

그리고 :

public final void stop() - 추천되고 있지 않습니다. 이 방법은 본질적으로 안전하지 않습니다.

스레드를 일시 중지하려는 경우 스레드 내에서 Object.wait()Objecft.notifyAll()을 사용해야합니다.

+1

안녕하세요, 답변 해 주셔서 감사합니다. while 루프에서 stop()을 join()으로 바꿨습니다. 스레드를 중지하기 전에 대기한다고 생각합니다. 그러나 나는 여전히 같은 문제가있다. 나는 무엇인가 놓치고 있는가? 실의 시작은. 스레드가 한 번 이상 오류 메시지가 시작될 수 없다는 것을 이해합니다. 그래서 스레드가 제대로 중지되지 않았기 때문에이 오류가 발생한다고 생각합니까? 감사합니다. – NioX5199

+1

@ NioX5199 : 아니요, join()은 스레드를 중지하지 않고 자체적으로 완료 될 때까지 기다립니다. 스레드가 이미 시작되었으므로 오류가 발생합니다. 스레드 *는 "중지"할 수 없으며 다시 시작할 수 없습니다. 내가 쓴 것처럼 : 조건이 충족 될 때까지 스레드를 일시 중지하려면 Object.wait()을 사용합니다. –

+0

그는 아마 그렇게하지 말아야합니다. 스레드를 다시 작성하는 것이 더 나은 방법 일 것입니다. – alexanderblom

0

나쁜 솔루션 만 작동 ..

public void surfaceCreated(SurfaceHolder holder) { 
     try{ 
     _thread.setRunning(true); 
     _thread.start(); 
     }catch(Exception ex){ 
      _thread = new TutorialThread(getHolder(), this); 
      _thread.start(); 
     } 

    } 

수정은 따뜻하게 환영합니다.

+0

이것이 작동하는 동안 (fsvo) 일반적으로 문제를 잡아 내지 않고 시도하고 수정하는 것이 좋지 않습니다. 대신, * 능동적 인 것으로 예외의 의미를 되 돌리십시오. –

5

내 의견으로는 스레드를 자주 시작하고 중지하려는 경우 코드를 팩의 하위 클래스로 묶어서는 안됩니다. 코드를 더 짧게 만들기 때문에 예제가 수행합니다. 대신에 Runnable을 사용하십시오. 그렇게하면 (자), 원의 thread를 정지 해 버려, 새로운 Thread 객체를 작성해, 다시 시작할 필요가있을 때 Runnable를 실행할 수 있습니다.

private TutorialRunnable tutorialRunnable; 

... 

// Synchronization and error checking omitted for brevity. 
public void surfaceCreated(SurfaceHolder holder) { 
    thread = new Thread(tutorialRunnable); 
    thread.start(); 
} 

public void surfaceDestroyed(SurfaceHolder holder) { 
    tutorialRunnable.setRunning(false); 
    while (thread != null) { 
     try { 
      thread.join(); 
      thread = null; 
     } catch (InterruptedException e) { 
     } 
    } 
} 

또한 예외에 의존하는 것은 나쁜 형식입니다. 그것은 자신의 코드가 예기치 않게 작동 할 때 최후의 수단으로 사용해야합니다.

관련 문제