0Pricing
Java Academy · 강의

반복 작업을 위한 ScheduledExecutorService

폴링과 백그라운드 유지 관리 작업을 위해 고정된 주기나 고정된 지연 시간으로 작업을 예약합니다.

반복 작업을 위한 ScheduledExecutorService은(는) CoddyKit의 무료 Java Academy 강의입니다. 이것은 4개 중 4번째 강의입니다. 아래에서 전체 강의를 무료로 읽을 수 있으며, 내장 코드 에디터와 24/7 AI 튜터와 함께 브라우저에서 직접 실습할 수 있습니다. 이 강의는 Java Academy 학습 경로의 일부이며, 진행 상황이 웹과 CoddyKit 앱에 동기화됩니다. Java Academy 강의에는 총 4개의 강의가 포함되어 있습니다.

ScheduledExecutorService를 사용하는 이유

ScheduledExecutorService는 작업 예약을 지원하도록 ExecutorService를 확장합니다. 스레드 풀을 기반으로 하며 예외에 안전한 스케줄러로 기존의 Timer/TimerTask 클래스를 대체합니다.

import java.util.concurrent.*;

ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(2);

// One-shot delay
scheduler.schedule(
    () -> System.out.println("Runs once after 3 seconds"),
    3, TimeUnit.SECONDS
);

// Don't forget to shut down eventually:
// scheduler.shutdown();

schedule: 한 번 실행하는 지연 작업

schedule(task, delay, unit)은 지정된 지연 시간 후 작업을 한 번 실행합니다. 실행 작업과 호출 가능 작업 모두에 사용할 수 있습니다.

ScheduledExecutorService s = Executors.newScheduledThreadPool(1);

// Runnable:
ScheduledFuture<?> sf1 = s.schedule(
    () -> System.out.println("Runnable fired!"), 2, TimeUnit.SECONDS);

// Callable:
ScheduledFuture<Integer> sf2 = s.schedule(
    () -> { System.out.println("Callable fired!"); return 42; },
    2, TimeUnit.SECONDS);

System.out.println(sf2.get()); // 42 (after 2 seconds)

scheduleAtFixedRate

scheduleAtFixedRate(task, initialDelay, period, unit)은 고정된 주기로 작업을 반복 실행합니다. 작업에 주기보다 오래 걸리면 다음 실행은 작업이 끝난 직후 시작됩니다. 실행이 겹치지는 않습니다.

ScheduledExecutorService s = Executors.newScheduledThreadPool(1);
AtomicInteger count = new AtomicInteger();

ScheduledFuture<?> sf = s.scheduleAtFixedRate(
    () -> System.out.println("Tick " + count.incrementAndGet()),
    0,   // initial delay
    1,   // period
    TimeUnit.SECONDS
);

Thread.sleep(5000);
sf.cancel(false); // stop after 5 ticks
s.shutdown();

scheduleWithFixedDelay

scheduleWithFixedDelay(task, initialDelay, delay, unit)은 각 작업이 완료된 AFTER 지정된 지연 시간만큼 기다린 후 다음 작업을 시작합니다. 작업 실행 시간이 일정하지 않은 폴링에 적합합니다.

s.scheduleWithFixedDelay(
    () -> {
        System.out.println("Polling... " + Instant.now());
        // variable-length polling task
    },
    0,  // no initial delay
    5,  // 5-second gap AFTER each completion
    TimeUnit.SECONDS
);
// Next execution = task end + 5 seconds (not task start)

고정 주기와 고정 지연 비교

핵심적인 차이는 다음과 같습니다.

  • scheduleAtFixedRate: 다음 시작 시점 = 마지막 시작 시점 + 주기(드리프트가 없는 타이밍)
  • scheduleWithFixedDelay: 다음 시작 시점 = 마지막 완료 시점 + 지연 시간(실행 사이의 간격이 보장됨)

하트비트에는 fixedRate를 사용하고, 작업 실행 시간이 일정하지 않은 폴링에는 fixedDelay를 사용합니다.

ScheduledFuture: 취소

schedule/scheduleAtFixedRate/scheduleWithFixedDelay는 ScheduledFuture를 반환합니다. 실행 중인 작업을 인터럽트하지 않고 이후 실행을 중지하려면 cancel(false)를 호출합니다.

ScheduledFuture<?> sf = scheduler.scheduleAtFixedRate(
    () -> System.out.println("Heartbeat"), 0, 1, TimeUnit.SECONDS);

// Cancel after 5 seconds
scheduler.schedule(() -> sf.cancel(false), 5, TimeUnit.SECONDS);

예약 작업의 예외 처리

예약된 작업에서 포착되지 않은 예외가 발생하면 스케줄러는 반복 실행을 조용히 중지합니다. 이후에는 더 이상 실행되지 않습니다. 항상 try-catch로 감쌉니다.

scheduler.scheduleAtFixedRate(() -> {
    try {
        // risky work
        if (Math.random() < 0.3) throw new RuntimeException("transient");
        System.out.println("Success");
    } catch (Exception e) {
        System.err.println("Task error: " + e.getMessage());
        // task continues to run on next interval
    }
}, 0, 2, TimeUnit.SECONDS);

실용 사례: 캐시 새로 고침

예약 작업을 사용하여 캐시를 주기적으로 새로 고칩니다.

class PriceCache {
    private volatile Map<String, Double> prices = new HashMap<>();
    
    PriceCache(ScheduledExecutorService scheduler) {
        scheduler.scheduleAtFixedRate(this::refresh, 0, 30, TimeUnit.SECONDS);
    }
    
    private void refresh() {
        System.out.println("Refreshing prices...");
        // prices = fetchFromDatabase();
    }
    
    Double getPrice(String symbol) { return prices.get(symbol); }
}

실용 사례: 백오프를 적용한 재시도

지수적 백오프 재시도를 예약된 작업으로 구현합니다:

void retryWithBackoff(Runnable task, int maxRetries, ScheduledExecutorService s) {
    AtomicInteger attempts = new AtomicInteger(0);
    long[] delay = {1}; // seconds
    
    Runnable wrapper = new Runnable() {
        public void run() {
            try {
                task.run();
            } catch (Exception e) {
                int n = attempts.incrementAndGet();
                if (n < maxRetries) {
                    delay[0] *= 2;
                    s.schedule(this, delay[0], TimeUnit.SECONDS);
                } else System.err.println("Max retries reached");
            }
        }
    };
    s.execute(wrapper);
}

모니터링: getDelay 및 getQueue

스케줄러의 상태를 확인합니다:

ScheduledFuture<?> sf = scheduler.schedule(() -> {}, 10, TimeUnit.SECONDS);
System.out.println("Delay remaining: " + sf.getDelay(TimeUnit.SECONDS) + "s");

// ThreadPoolExecutor provides queue inspection:
if (scheduler instanceof ScheduledThreadPoolExecutor ste) {
    System.out.println("Queue size: " + ste.getQueue().size());
}

종료 및 비우기

종료할 때 예약된 작업을 계속 실행할지 결정합니다:

ScheduledThreadPoolExecutor ste = (ScheduledThreadPoolExecutor)
    Executors.newScheduledThreadPool(2);

// Cancel scheduled tasks on shutdown (default: false = they run)
ste.setExecuteExistingDelayedTasksAfterShutdownPolicy(false);
ste.setContinueExistingPeriodicTasksAfterShutdownPolicy(false);

ste.shutdown();

빠른 확인

scheduleAtFixedRate(..., 1, TimeUnit.SECONDS)로 예약된 작업이 완료하는 데 3초가 걸립니다. 스케줄러는 이를 어떻게 처리합니까?

다시 보기: ScheduledExecutorService

핵심 정리:

  • schedule() — 지연 후 한 번 실행
  • 고정 주기 예약 — 드리프트 없는 타이밍(시작 시점 간격)
  • 고정 지연 예약 — 항상 일정한 간격 보장(완료 후 다음 시작)
  • 처리되지 않은 예외가 발생하면 반복 작업이 조용히 중단되므로 항상 try-catch로 감쌉니다
  • ScheduledFuture.cancel(false)로 취소

자주 묻는 질문

“반복 작업을 위한 ScheduledExecutorService” 강의는 무료인가요?

네 — “반복 작업을 위한 ScheduledExecutorService” 전체 내용을 이 웹사이트에서 무료로 읽을 수 있습니다. 인터랙티브하게 실습하려면(내장 코드 에디터와 24/7 AI 튜터), CoddyKit PRO로 업그레이드하면 Java Academy 강의 전체를 잠금 해제할 수 있습니다. Java Academy 강의에는 총 4개의 강의가 포함되어 있습니다.

“반복 작업을 위한 ScheduledExecutorService”에서 뭘 배우나요?

폴링과 백그라운드 유지 관리 작업을 위해 고정된 주기나 고정된 지연 시간으로 작업을 예약합니다. 브라우저에서 직접 실행하는 실습 코드로 Java Academy을(를) 배우며, 24/7 AI 튜터가 강의를 진행하면서 질문에 답변해줍니다.

Java Academy을(를) 시작하는 데 경험이 필요한가요?

사전 경험은 필요하지 않습니다. CoddyKit의 Java Academy은(는) 초급자부터 고급 학습자까지를 위해 구성되어 있으므로, 여기서 시작하거나 처음부터 시작할 수 있으며 자신의 속도대로 진행할 수 있습니다. 이것은 4개 중 4번째 강의입니다.

“반복 작업을 위한 ScheduledExecutorService” 강의는 얼마나 걸리나요?

대부분의 CoddyKit 강의는 약 5~10분이 소요됩니다. 각 강의는 간결하고 인터랙티브하여 꾸준한 진행이 가능하며, 웹과 앱에서 중단한 부분부터 바로 시작할 수 있습니다.

이 Java Academy 강의에서 코드를 작성하고 실행할 수 있나요?

네. 모든 Java Academy 강의에는 내장 코드 에디터가 포함되어 있으므로, 브라우저에서 바로 실제 코드를 작성하고 실행한 후 즉시 AI 피드백을 받을 수 있습니다 — 로컬 설정이 필요 없습니다.

이 강의의 모든 강의

  1. ExecutorService와 스레드 풀 유형
  2. 작업 제출: Runnable과 Callable
  3. Future와 오류 처리
  4. 반복 작업을 위한 ScheduledExecutorService
← Java Academy(으)로 돌아가기