2016-08-27 2 views
1

클래스가 서버에서 데이터 업데이트를 정기적으로 기다리는 클래식 서버/클라이언트 문제가 있습니다. 다음과 같이 간단히 말해서 내 프로그램은 다음과 같습니다Java 동기화 - 서버에서 데이터 대기 중

public synchronized void eodProcess() { 
    //DO STUFF 
    dataReady = false; 
    while (!dataReady) { 
     try { 
      wait(); 
     } catch (InterruptedException e) { 
     } 
    } 
    //DO STUFF 
    } 

public void update(){ 
    //CODE THAT DOWNLOADS FROM SERVER 
    synchronized(this){ 
     dataReady = true; 
     notifyAll(); 
    } 
} 

모두 eodProcess() 및 업데이트()는 매일 저녁 같은 시간에 실행되도록 예정이다.

위의 코드는 데이터 다운로드에 몇 초가 걸리는 것처럼 항상 효과가 있었지만 이론적으로 update()가 eodProcess()보다 빠르게 실행되고 dataReady를 true로 설정 했으므로 잘못된 방법으로 보입니다. eodProcess는 False로 설정 한 다음 영원히 기다립니다. eodProcess가 데이터를 준비 할 때까지 기다리는 올바른 방법은 무엇입니까?

나는 두 개의 메소드 중 하나가 나오기 전에 dataReady를 false로 설정하고 eodProcess의 시작 부분에서 초기화를 제거하는 새로운 프로세스를 계획하고 있지만 매우 깨끗하지는 않습니다.

감사합니다,

+0

프로세스에 대해 이야기 할 때 스레드를 의미한다고 생각합니다. – mszymborski

+0

누가 다운로드해야하는지 결정합니까? 다운로드 할 예정인 작업을 Callable에 캡슐화 한 다음 ExecutorService에 제출하여 미래를 되 찾는 것이 좋습니다. 그런 다음'future.get()'은 다운로드가 완료 될 때까지 차단합니다 (eodProcess에서 호출 할 수 있습니다). 그러나 BlockingQueue 나 심지어는 모든 것을 스레딩하는 것처럼 작동 할 수있는 다른 모델도 있습니다. 이 문제는 한 가지 답변을 다른 답변보다 추천 할만한 충분한 정보를 제공하지 못하므로 너무 광범위합니다. – yshavit

+0

@yshavit, 고마워요 - ExecutorService를보고 있는데 너무 효과가있는 것처럼 보입니다. 싱글 스레딩은 기존 코드의 상당한 재 작성 없이는 작동하지 않습니다. 매일 같은 데이터가 스케줄러를 통해 다운로드됩니다. 데이터베이스에서 매일 데이터를 가져 와서 정리하십시오. – alex314159

답변

1

CountDownLatch의 응용 프로그램이 유용 할 때 고전적인 상황이다.

CountDownLatch downloadDone = new CountDownLatch(1); 

[...] 

public synchronized void eodProcess() { 
    //DO STUFF 

    downloadDone.await(); 
    //DO STUFF 
    } 

public void update(){ 
    //CODE THAT DOWNLOADS FROM SERVER 
    downloadDone.countDown(); 
} 

기본적으로 세마포어이지만 좋네요. Await은 래치가 0으로 카운트 다운 될 때 (또는 스레드가 인터럽트 된 경우)에만 진행됩니다. 카운트를 재설정하는 기능이 필요하면 CyclicBarrier을 사용하는 것이 좋습니다 (거의 동일하게 작동하지만, reset 방법이 있습니다).

+0

감사합니다. 그럼 eodProcess에서 동기화를 제거 할 수 있습니까? – alex314159

+0

@ alex314159 : 예. 래치는 자체적으로 동기화 문제를 처리합니다. – mszymborski

+0

오른쪽 -이 트릭을해야합니다. 저를 소개해 주셔서 감사합니다. eodProcess가 끝날 때 래치를 다시 생성하여 카운트를 재설정하고 (그 다음날 준비 할 수 있습니까?) – alex314159