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 ในทันที — ไม่ต้องติดตั้งในเครื่องของคุณ
บทเรียนทั้งหมดในหลักสูตรนี้
- ExecutorService และชนิดพูลเธรด
- การส่งงาน: Runnable กับ Callable
- Future และการจัดการข้อผิดพลาด
- ScheduledExecutorService สำหรับงานที่ทำซ้ำ