Skip to content

09.4 — 异步任务与定时任务

**返回 进阶源码索引**


1. 定时任务

java
@Configuration
@EnableScheduling
public class SchedulingConfig {
    
    @Bean
    public TaskScheduler taskScheduler() {
        ThreadPoolTaskScheduler scheduler = new ThreadPoolTaskScheduler();
        scheduler.setPoolSize(5);
        scheduler.setThreadNamePrefix("scheduled-");
        scheduler.setWaitForTasksToCompleteOnShutdown(true);
        scheduler.setAwaitTerminationSeconds(30);
        return scheduler;
    }
}

@Component
public class ScheduledTasks {
    
    // cron 表达式:秒 分 时 日 月 周
    @Scheduled(cron = "0 0 2 * * ?")  // 每天凌晨2点
    public void dailyReport() {
        System.out.println("生成日报...");
    }
    
    // 固定间隔(两次调用之间)
    @Scheduled(fixedDelay = 5000)  // 上次执行完 5 秒后
    public void processDelay() {
        System.out.println("Fixed delay task...");
    }
    
    // 固定速率(不考虑执行时间)
    @Scheduled(fixedRate = 10000)  // 每 10 秒执行一次
    public void processRate() {
        System.out.println("Fixed rate task...");
    }
    
    // 首次延迟
    @Scheduled(initialDelay = 10000, fixedRate = 5000)
    public void delayedTask() {
        System.out.println("Delay 10s then every 5s");
    }
}

注意事项

  • 默认单线程:默认的 @EnableScheduling 使用单线程执行器,所有任务共享一个线程
  • 配置线程池:必须配置 TaskScheduler 避免任务互相阻塞
  • 异常处理:schedule 不捕获异常,一个任务的异常不会影响其他任务(单线程模式下,未捕获异常会杀死线程池中的线程)
  • 分布式锁:多实例部署时需配合分布式锁,防止任务重复执行

2. 异步支持

java
@Configuration
@EnableAsync
public class AsyncConfig implements AsyncConfigurer {
    
    @Override
    public Executor getAsyncExecutor() {
        ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
        executor.setCorePoolSize(5);
        executor.setMaxPoolSize(10);
        executor.setQueueCapacity(100);
        executor.setThreadNamePrefix("async-");
        executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
        executor.initialize();
        return executor;
    }
    
    @Override
    public AsyncUncaughtExceptionHandler getAsyncUncaughtExceptionHandler() {
        return (ex, method, params) -> {
            log.error("Async method [{}] threw exception", method.getName(), ex);
        };
    }
}

@Component
public class AsyncService {
    
    @Async
    public CompletableFuture<String> processAsync(String data) {
        // 异步执行
        return CompletableFuture.completedFuture("Processed: " + data);
    }
    
    @Async
    public void fireAndForget() {
        // 无返回值异步
    }
}

@Async 失效场景

与 **@Transactional 同方法失效** 同理,@Async 也基于 AOP 代理。

java
@Service
public class NotificationService {
    
    public void sendBatch() {
        this.sendEmail();  // ❌ @Async 不生效(直接调用 this 引用)
    }
    
    @Async
    public void sendEmail() {
        // ...
    }
}

注意事项

  • 默认代理方式:Spring Boot 默认使用 CGLIB 代理
  • 返回值限制:只能返回 voidFutureAsyncResultCompletableFuture
  • 异常处理:无返回值方法抛出的异常由 AsyncUncaughtExceptionHandler 处理
  • @Async + @Transactional:组合使用时注意——@Async 让方法在独立线程执行,@Transactional 在该线程的事务上下文中生效,两者互不干扰

Knowledge4J — Java 知识库