0Pricing
Java Academy · บทเรียน

ScheduledExecutorService สำหรับงานที่ทำซ้ำ

ตั้งเวลางานให้ทำซ้ำตามอัตราคงที่หรือมีระยะหน่วงคงที่ สำหรับการตรวจสอบเป็นระยะและงานบำรุงรักษาเบื้องหลัง

ScheduledExecutorService สำหรับงานที่ทำซ้ำ เป็นบทเรียน Java Academy ฟรีบน CoddyKit นี่คือบทเรียนที่ 4 จากทั้งหมด 4 บทเรียน คุณสามารถอ่านบทเรียนทั้งหมดด้านล่างฟรี — จากนั้นลองปฏิบัติด้วยตัวคุณเองในเบราว์เซอร์พร้อมตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7 บทเรียนนี้เป็นส่วนหนึ่งของเส้นทางการเรียน 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) จะทำงานหนึ่งครั้งหลังจากการหน่วงเวลาที่ระบุ ใช้ได้ทั้งกับ Runnable และ Callable

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) จะรอการหน่วงเวลาที่ระบุหลังจากแต่ละงานเสร็จ ก่อนเริ่มงานถัดไป เหมาะสำหรับการตรวจสอบเป็นระยะเมื่องานใช้เวลาไม่คงที่

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() — ทำงานครั้งเดียวพร้อมการหน่วงเวลา
  • scheduleAtFixedRate() — การจับเวลาที่ไม่คลาดเคลื่อน (จากจุดเริ่มต้นถึงจุดเริ่มต้น)
  • scheduleWithFixedDelay() — รับประกันช่วงห่าง (จากจุดสิ้นสุดถึงจุดเริ่มต้น)
  • ข้อยกเว้นที่ไม่มีการดักจับจะหยุดงานที่ทำซ้ำอย่างเงียบ ๆ — ให้ครอบด้วย try-catch เสมอ
  • ยกเลิกด้วย ScheduledFuture.cancel(false)

คำถามที่พบบ่อย

บทเรียน “ScheduledExecutorService สำหรับงานที่ทำซ้ำ” ฟรีหรือไม่

ใช่ — ข้อความเต็มของ “ScheduledExecutorService สำหรับงานที่ทำซ้ำ” ฟรีให้อ่านที่นี่บนเว็บ เพื่อปฏิบัติแบบโต้ตอบ (ตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7) และปลดล็อคส่วนที่เหลือของคอร์ส Java Academy ให้อัปเกรดเป็น CoddyKit PRO คอร์ส Java Academy มีบทเรียนทั้งหมด 4 บทเรียน

คุณจะเรียนรู้อะไรในบทเรียน “ScheduledExecutorService สำหรับงานที่ทำซ้ำ”

ตั้งเวลางานให้ทำซ้ำตามอัตราคงที่หรือมีระยะหน่วงคงที่ สำหรับการตรวจสอบเป็นระยะและงานบำรุงรักษาเบื้องหลัง คุณปฏิบัติ Java Academy ด้วยโค้ดที่ใช้งานได้จริงที่คุณเรียกใช้โดยตรงในเบราว์เซอร์ และติวเตอร์ AI ตลอด 24/7 ตอบคำถามของคุณขณะที่คุณไปผ่านบทเรียน

คุณต้องมีประสบการณ์ก่อนที่จะเริ่มเรียน Java Academy หรือไม่

ไม่จำเป็นต้องมีประสบการณ์มาก่อน Java Academy บน CoddyKit ออกแบบมาสำหรับผู้เริ่มต้นไปจนถึงผู้เรียนขั้นสูง คุณสามารถเริ่มต้นที่นี่หรือเริ่มจากตัวแรกและเรียนด้วยความเร็วของคุณเอง นี่คือบทเรียนที่ 4 จากทั้งหมด 4 บทเรียน

บทเรียน “ScheduledExecutorService สำหรับงานที่ทำซ้ำ” ใช้เวลานานแค่ไหน

บทเรียน CoddyKit ส่วนใหญ่ใช้เวลาประมาณ 5–10 นาที แต่ละบทเรียนจึงสั้นและเป็นแบบโต้ตอบ คุณสามารถก้าวหน้าอย่างต่อเนื่องและกลับมาเรียนต่อจากตรงที่เพิ่งหยุดบนเว็บและแอปได้เลย

ฉันเขียนและรันโค้ดในบทเรียน Java Academy นี้ได้ไหม

ได้ บทเรียน Java Academy ทุกบทมีตัวแก้ไขโค้ดในตัว คุณจึงเขียนและรันโค้ดจริงได้เลยในเบราว์เซอร์ และได้รับข้อเสนอแนะจาก AI ในทันที — ไม่ต้องติดตั้งในเครื่องของคุณ

บทเรียนทั้งหมดในหลักสูตรนี้

  1. ExecutorService และชนิดพูลเธรด
  2. การส่งงาน: Runnable กับ Callable
  3. Future และการจัดการข้อผิดพลาด
  4. ScheduledExecutorService สำหรับงานที่ทำซ้ำ
← กลับไปที่ Java Academy