프로그램/Java

[Java] 프로그램 루프(Loop) 내에서 스래드 슬립(sleep)을 얼마를 주면 되고 주는 이유는?

neorc 2025. 11. 28. 15:00

프로그램 반복 루프 내에서 Thread.sleep()을 주는 시간은 루프의 목적에 따라 달라집니다. 단순히 정해진 값은 없으며, 반응성(Latency)과 CPU 자원(Resource) 사이의 균형을 맞춰야 합니다.

엔지니어로서의 배경을 고려하여 시나리오별 권장 값과 그 이유를 정리해 드립니다.

1. 시나리오별 권장 시간

시나리오권장 시간설명
초고속 대기 (Spin-wait) 0ms ~ 1ms 즉각적인 반응이 필요할 때(예: 게임 루프, 초단타 매매). 단, sleep(0)은 OS 스케줄러에 따라 동작이 다를 수 있어 sleep(1)이 더 안전합니다 ​.
일반적인 폴링 (Polling) 100ms ~ 500ms DB나 파일 변경 감지 등. 100ms는 사람이 '즉시'라고 느끼는 한계 시간이므로, UX에 영향 없이 자원을 아낄 수 있습니다.
API 호출 / 네트워크 1000ms 이상 외부 서버의 Rate Limit(요청 제한)에 맞춰야 합니다. 너무 빠르면 IP가 차단될 수 있습니다 ​.
UI / 애니메이션 ~16ms 60 FPS(초당 60프레임)를 맞추기 위해 약 16ms(1000/60) 주기로 갱신합니다.
 

2. 추가하는 이유 (핵심: 바쁜 대기 방지)

가장 큰 이유는 CPU 점유율(Busy Waiting) 방지입니다.

  • CPU 과열 및 배터리 소모 방지: sleep 없이 while(true)를 돌리면 해당 스레드는 CPU 코어 하나를 100% 점유하게 됩니다. 이는 노트북의 배터리를 광속으로 소모시키고 발열을 유발합니다. Thread.sleep(1)만 주어도 CPU 점유율은 거의 0% 가까이 떨어집니다.
  • 컨텍스트 스위칭 (Context Switching): sleep을 호출하면 현재 스레드는 RUNNABLE 상태에서 TIMED_WAITING 상태로 변합니다. 이 틈에 OS 스케줄러가 다른 스레드나 프로세스에게 CPU 자원을 할당할 수 있게 되어 전체 시스템의 멀티태스킹 성능이 보장됩니다.

3. 개발자를 위한 팁 (Best Practices)

질문하신 분께서 자바 네트워크나 트레이딩 알고리즘을 다루시므로, 단순 sleep보다 더 나은 패턴들을 추천합니다.

  • ScheduledExecutorService 사용: 단순 무한 루프에 sleep을 넣는 것보다, 자바 5부터 도입된 ScheduledExecutorService를 사용하는 것이 스레드 관리와 예외 처리 면에서 훨씬 안전하고 우아한 방법입니다.
  • 이벤트 기반 처리 (wait / notify): 특정 조건이 만족될 때만 깨어나야 한다면, 루프를 돌며 감시(Polling)하는 것보다 Object.wait()와 notify()를 사용하여 불필요한 CPU 사용을 원천 차단하는 것이 좋습니다.
  • Java 9+ Thread.onSpinWait(): 만약 나노초 단위의 극도로 짧은 대기(Spin-lock 등)가 필요한 상황이라면 sleep 대신 Thread.onSpinWait() 힌트를 사용하여 CPU에게 "잠깐 멈추라"는 신호를 주는 것이 더 효율적입니다.
  •  
// 1초마다 실행 (권장) 
ScheduledExecutorService scheduler = Executors.newSingleThreadScheduledExecutor(); 
scheduler.scheduleAtFixedRate(() -> { /* 로직 */ }, 0, 1, TimeUnit.SECONDS);

 

요약하자면: 일반적인 백그라운드 작업이라면 100ms, 외부 API 통신이라면 1초 이상(또는 Rate Limit)을 기준으로 잡으시면 됩니다.