2010-08-21 5 views
42

NetBeans에 다음과 같은 새로운 힌트가 있습니다. 루프에서 Thread.sleep이 호출되었습니다.NetBeans/Java/New 힌트 : 루프에서 호출 된 Thread.sleep

질문 1 : 언제 어떻게 반복해서 잠을 자는데 문제가 될 수 있습니까?

질문 2 : 문제가 있다면 대신 무엇을해야합니까?

업데이트 : 질문 3 : 여기에 몇 가지 코드가 있습니다. 루프에서 Thread.Sleep 대신 다른 것을 사용해야한다면이 경우에 대해 알려주십시오. 요컨대, 이것은 클라이언트 TCP 연결을 청취하는 서버에 의해 사용됩니다. 절전 모드는 클라이언트와의 세션 수가 최대 인 경우에 사용됩니다. 이 상황에서 무료 세션을 사용할 수있게 될 때까지 응용 프로그램을 대기시키고 싶습니다.

public class SessionManager { 
    private static final int DEFAULT_PORT = 7500; 
    private static final int SLEEP_TIME = 200; 
    private final DatabaseManager database = new DatabaseManager(); 
    private final ServerSocket serverSocket = new ServerSocket(DEFAULT_PORT); 

public SessionManager() throws IOException, SQLException 
{ 
} 

public void listen() 
{ 
while (true) 
    if (Session.getSessionCount() < Session.getMaxSessionCount()) 
     try 
     { 
      new Thread(new Session(database, serverSocket.accept())).start(); 
     } 
     catch (IOException ex) { ex.printStackTrace(); } 
    else 
     try 
     { 
      Thread.sleep(SLEEP_TIME); 
     } 
     catch (InterruptedException ex) { ex.printStackTrace(); } 
} 

public static void main(String[] args) throws IOException, SQLException 
{ 
new SessionManager().listen(); 
} 
} 

답변

19

일반적으로 루프에서 절전 모드를 호출하면 성능이 저하됩니다. 예 :

while (true) { 
    if (stream.available() > 0) { 
     // read input 
    } 
    sleep(MILLISECONDS); 
} 

MILLISECONDS가 너무 큰 경우이 코드는 입력이 가능함을 인식하는 데 오랜 시간이 걸립니다.

MILLISECONDS가 너무 작 으면이 코드는 아직 도착하지 않은 입력에 대한 많은 시스템 리소스 확인을 낭비합니다.

루프에서 sleep의 다른 용도는 일반적으로 의심 스럽습니다. 보통 더 좋은 방법이 있습니다.

문제가 발생하면 어떻게해야합니까?

코드를 게시하면 도움이 될만한 답을 줄 수 있습니다.

편집은 IMO, 문제를 해결하기 위해 더 나은 방법은 ThreadPoolExecutor를 사용하는 것입니다. 이 같은

뭔가 :

public void listen() { 
    BlockingQueue queue = new SynchronousQueue(); 
    ThreadPoolExecutor executor = new ThreadPoolExecutor(
      1, Session.getMaxSessionCount(), 100, TimeUnit.SECONDS, queue); 
    while (true) { 
     try { 
      queue.submit(new Session(database, serverSocket.accept())); 
     } catch (IOException ex) { 
      ex.printStackTrace(); 
     } 
    } 
} 

이 코드가 현재 작동하는 방식에 맞게 집행을 구성합니다. 네가 할 수있는 다른 방법이 많이있다. 위의 javadoc 링크를 참조하십시오.

+0

java.util.Timer 및주기적인 TimerTask는 어떻습니까? – Core

+0

@Core - 사용 방법에 따라 다릅니다. 'sleep()'과 같은 것을 구현하기 위해서이 함수를 사용한다면, sleep()을 사용할 때와 같은 문제가있다. –

+0

우리는 managedexecutorservice를 어떻게 사용합니까? – wib

2

언제/어떤 일정으로 잠을 자는데 문제가 될 수 있습니까?
때때로 사람들은 적절한 동기화 방법 대신 대기/알림을 사용합니다.

문제가 발생하면 어떻게해야합니까?
현재 진행중인 작업에 따라 다릅니다. 이 작업을 수행하는 것이 최선의 방법이라고 상상하는 것이 어려울지라도 가능한 일이라고 생각합니다.

이 주제에 대해 을 확인할 수 있습니다.

+0

사람들은 때때로 가능한 테스트()와 함께 읽기 루프에서 사용. – EJP

+0

한 가지 용도는 특정 기간보다 오래된 파일을 삭제하는 디렉토리 클리너입니다. 첫 번째 실행 후 가장 오래된 파일이 무엇인지, "너무 오래되었습니다"때까지 정확히 얼마 동안인지 알 수 있으므로 해당 기간 동안 잠들 수 있습니다. – Jesse

+0

@Jesse - 스케줄 된 스레드 풀 실행 프로그램이 아마도 더 좋을 것입니다. –

3

다른 사람들은 사용법에 따라 다릅니다.합법적 인 사용은 매 10 초마다 무언가를하도록 설계된 프로그램입니다 (그러나 정확한 타이밍이 필요하지는 않습니다). 몇 분마다 데이터 및 기타 작업을 가져 오는 "유틸리티 앱"이 많이 있습니다. 이것은 이러한 작업을 수행하는 쉬운 방법이며 일반적으로 절전 간격을 매우 낮게 설정하고 카운터를 사용하여 프로그램이 응답을 유지하고 쉽게 종료 할 수 있도록합니다.

int count = 0; 
while (true) { 

    try { 
     // Wait for 1 second. 
     Thread.sleep(1000); 
    } 
    catch (InterruptedException ex) {} 

    // Check to see if the program should exit due to other conditions. 
    if (shouldExit()) 
     break; 

    // Is 10 seconds up yet? If not, just loop back around. 
    count++; 
    if (count < 10) continue; 

    // 10 seconds is up. Reset the counter and do something important. 
    count = 0; 
    this.doSomething(); 
} 
+1

대신에 예약 된 스레드 풀 실행 프로그램을 사용하는 것이 대부분의 경우 기술적으로 더 좋을 수도 있지만, 때로는 뭔가 빠르고 간단하게 프로그래밍 할 때 너무 많습니다. – mjaggard

+0

@mjaggard는 현재 내부에 수면이있는 루프가있는 스레드가 있다고 말할 수 있습니다. 더 이상 관련이없는 오래된 데이터를 제거하는 등의 관리 작업을 수행하고 있습니다. 스케줄 된 스레드 풀 실행 프로그램을 사용하면 코드에 불필요한 복잡성이 추가됩니다. 컨텍스트 스위치 페널티는 잠자고있는 오래 지속되는/유휴 스레드에 대해서는 무시해도 좋습니다. "좋은 연습이 아닙니다"경고를 제거하는 것 이외에 예약 된 스레드 풀이 실제로 어떤 것을 당신에게 사주 는가? – ruckc

+2

각 코드를 작성 했습니까? 나는 예정된 스레드 풀 Executor 버전이 실제로 더 짧고, 읽기 쉽고, 매우 유사한 것으로 생각한다. – mjaggard

1

는 내가 루프에서 sleep() 방법 중 하나 개를 완전히 합법적 인 사용을 건너 생각합니다.

우리는 서버와 클라이언트 사이의 단방향 연결이 있습니다. 따라서 클라이언트가 서버와의 비동기 통신을 원할 때 서버에 메시지를 보내고 주기적으로 서버의 응답을 폴링하는 것보다. 타임 아웃 간격이 필요합니다. 그들은 단지 대신 시간과 공간을 낭비 읽기에 차단해야 할 때

Response resp = null; 
for (int i = 0; i < POLL_REPEAT && resp == null; i++) { 
    try { 
     Thread.sleep(POLL_INTERVAL); 
    } catch (InterruptedException ie) { 
    } 
    resp = server.getResponse(workflowId); 
} 

POLL_REPEAT * POLL_INTERVAL ~ 시간 제한 간격

+1

가능한 한 더 나은 솔루션은 새 데이터를 사용할 수있을 때까지 대기하는 차단 IO 메서드를 사용하는 것입니다. – Vitruvius

관련 문제