如何在Java中重复执行多个任务并在指定时间后停止?
Got it, let's build out a complete, robust solution for running multiple repeating tasks that automatically stop after a set amount of time. You’re already on the right track with ScheduledExecutorService—it’s way more reliable than managing raw Thread instances for scheduled work. Here’s a fully working implementation with explanations of key parts:
Complete Implementation for Multiple Repeating Tasks with Auto-Stop
Step 1: Full Working Code
import java.time.LocalDateTime; import java.util.concurrent.Executors; import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.TimeUnit; public class ScheduledMultiTaskRunner { public static void main(String[] args) { // Configure how long to run all tasks before stopping (e.g., 15 seconds) final long RUN_DURATION_SECONDS = 15; // Create a scheduled thread pool with enough threads for parallel task execution // We have 2 tasks here, so a pool size of 2 ensures they run concurrently ScheduledExecutorService taskExecutor = Executors.newScheduledThreadPool(2); // -------------------------- // Define your repeating tasks // -------------------------- Runnable helloTask = () -> { try { System.out.println("Hello World! | Current time: " + LocalDateTime.now().toLocalTime()); } catch (Exception e) { // Critical: Catch exceptions to prevent the task from being dropped by the executor System.err.println("Hello task failed: " + e.getMessage()); } }; Runnable statusCheckTask = () -> { try { System.out.println("Status Check: All tasks running | Time: " + LocalDateTime.now().toLocalTime()); } catch (Exception e) { System.err.println("Status task failed: " + e.getMessage()); } }; // -------------------------- // Schedule tasks to repeat // -------------------------- // Task 1: Starts immediately, repeats every 2 seconds taskExecutor.scheduleAtFixedRate(helloTask, 0, 2, TimeUnit.SECONDS); // Task 2: Starts after a 1-second delay, repeats every 3 seconds taskExecutor.scheduleAtFixedRate(statusCheckTask, 1, 3, TimeUnit.SECONDS); // -------------------------- // Schedule auto-stop after RUN_DURATION_SECONDS // -------------------------- taskExecutor.schedule(() -> { System.out.println("\n--- Time's up! Stopping all tasks ---"); // Graceful shutdown: Stop accepting new tasks, wait for running tasks to finish taskExecutor.shutdown(); try { // Wait up to 5 seconds for tasks to complete gracefully if (!taskExecutor.awaitTermination(5, TimeUnit.SECONDS)) { // Force shutdown if tasks don't finish in time System.out.println("Forcing shutdown of remaining tasks..."); taskExecutor.shutdownNow(); } } catch (InterruptedException e) { // If we're interrupted while waiting, force shutdown immediately taskExecutor.shutdownNow(); // Restore the interrupted status for the calling thread Thread.currentThread().interrupt(); } System.out.println("All tasks have stopped successfully."); }, RUN_DURATION_SECONDS, TimeUnit.SECONDS); } }
Key Components Explained
Let’s break down the important parts to make sure you understand how everything works:
- Thread Pool Size: We use
newScheduledThreadPool(2)because we have 2 tasks. Using a pool size matching your task count ensures tasks run in parallel without waiting for each other. If you have more tasks, adjust the number accordingly. - Exception Handling in Tasks: Each task includes a
try-catchblock. If a task throws an uncaught exception,ScheduledExecutorServicewill stop scheduling that task entirely—so catching exceptions ensures your task keeps running even if something goes wrong. scheduleAtFixedRatevsscheduleWithFixedDelay:- We use
scheduleAtFixedRatehere, which schedules the next run based on the start time of the previous run (e.g., every 2 seconds, regardless of how long the task takes). - If you want the next run to start after the previous task finishes, use
scheduleWithFixedDelayinstead.
- We use
- Graceful Shutdown:
shutdown()tells the executor to stop accepting new tasks and let existing ones finish.awaitTermination()waits a set time for tasks to complete. If they don’t finish in time,shutdownNow()forces them to stop by interrupting running threads.
- Auto-Stop Trigger: We use
taskExecutor.schedule()to run the shutdown logic after our desired run duration. This avoids needing a separate monitoring thread.
Bonus: Cancel Individual Tasks
If you ever need to stop just one task instead of all of them, you can capture the ScheduledFuture returned by scheduleAtFixedRate and call cancel() on it:
// Capture the future when scheduling the task ScheduledFuture<?> helloTaskFuture = taskExecutor.scheduleAtFixedRate(helloTask, 0, 2, TimeUnit.SECONDS); // Later, cancel the task (false = don't interrupt if it's currently running) helloTaskFuture.cancel(false);
内容的提问来源于stack exchange,提问作者user3718160
相关产品推荐
相关产品推荐

