2017-10-25 5 views
0

Service.java 내의 Start TimeThread.java Service.java가 중복 실행되면 문제가 발생합니다.중복 서비스 및 동기화

왜 'isWait'값이 'Log.d ("isRun1")'에서 true이고 'Log.d ("isRun2")'에서 거짓입니까?

'중복 서비스 실행'과 '동기화 됨'에 대해 궁금합니다.

내 코드는 다음과 같습니다

Service.java

thread.pauseNrestart(false); 

Thread.java

public class TimeThread extends Thread { 

Handler handler; 
boolean isRun = true; 
boolean isWait = false; 

public TimeThread(Handler handler) { 
    this.handler = handler; 
} 

public void pauseNResume(boolean isWait) { 

    synchronized (this) { 

     this.isWait = isWait; 
      *Log.d("isRun1 :" + isRun + "");* 
     notify(); 
    } 
} 

public void run() { 
    while (isRun) { 
     *Log.d("isRun2 :" + isRun + "");* 
     try { 
      Thread.sleep(1000); 
     } catch (Exception e) { 
      // TODO: handle exception 
     } 
     if (isWait) { 
      try { 
       synchronized (this) { 
        wait(); 
       } 
      } catch (Exception e) { 
       // TODO: handle exception 
      } 
     } 
     handler.sendEmptyMessage(0); 
    } 
} 

}

최적화가 일어날 때 코드의

답변

0

특정 라인 순서가 변경 될 수 있습니다
- 컴파일러는 공동 작업 할 때 코드를 최적화합니다. 사물을 재정렬하는 것에 의한 mpiling;
- JVM은 순서를 변경하여 코드를 동적으로 최적화 할 수 있습니다.
- 하드웨어가 순서를 변경하여 성능을 최적화 할 수 있습니다.

그래서 코드의 섹션

this.isWait = isWait; 
*Log.d("isRun1 :" + isRun + "");* 

이 라인을 가지고 할 수 있음을 전환했다.

이것은 또한 가시성 문제가 될 수 있습니다. 때로는 다른 스레드에서 효과가 보이지 않을 수도 있습니다.

while 루프를 검사 할 때 동기화 된 섹션이 아니므로 pauseNResume을 다른 곳에서 호출하면 상황이 바뀔 수 있습니다. 언급 한 바와 같이 이러한 변경 사항은 스레드에 즉시 표시되지 않을 수도 있습니다.

isRun 및 isWait을 volatile로 선언 해보십시오. 휘발성은 해당 변수에 대한 읽기 및 쓰기가 재정렬되지 않도록합니다. 위의 코드 섹션에서 행이 바뀌면 문제가 해결 될 것이므로 isWait 변수가 변경된 후 항상 인쇄됩니다.

그러나 while 루프 상태 검사에서 이러한 부울을 사용하는 방법에 대해서는 정상적인 부울 대신 AtomicBoolean을 사용하는 것이 좋습니다.

+0

"서비스 실행 중복"이라는 질문 섹션에서 질문하는 내용이 너무 많지 않습니다 ... 안드로이드와 관련이있을 수 있습니다 - 안드로이드에 대한 지식은 제한적입니다. 위의 대답은 Java의 동시성과 관련이 있습니다. – Smiley

+0

나는 그것에 대해 더 많이 생각할 수있다. 답변 주셔서 감사합니다. – mmoa

+0

@mmoa 귀하의 질문을 다시 읽습니다. "서비스 실행 중 복제"가 하나 이상의 스레드가 실행 중임을 의미합니다 ("Service.java 내부에서 TimeThread.java 시작"). 하나의 스레드만으로는 문제가 발생하지 않지만 두 스레드는 다른 스레드에 영향을주는 사항을 변경하거나 동시성의 가시성 문제로 인해 다른 스레드가 볼 수없는 변경 사항을 적용 할 수 있습니다. 또한 busy 루프 대신 [Conditions] (https://docs.oracle.com/javase/8/docs/api/java/util/concurrent/locks/Condition.html)를 사용하면 실행/대기를 확인하는 데 유용합니다. – Smiley