Spring Boot 定时任务以及异步任务的实现

06-01 1289阅读

一、定时任务

在 Spring Boot 中,实现定时任务非常简单,主要通过 @Scheduled 注解和 TaskScheduler 接口来实现。以下是实现定时任务的详细步骤和方法:

  1. 启用定时任务支持
    • 在 Spring Boot 应用中,首先需要启用定时任务支持。可以通过在配置类或主应用类上添加 @EnableScheduling 注解来实现。
      import org.springframework.boot.SpringApplication;
      import org.springframework.boot.autoconfigure.SpringBootApplication;
      import org.springframework.scheduling.annotation.EnableScheduling;
      @SpringBootApplication
      @EnableScheduling // 启用定时任务支持
      public class MyApplication {
      	public static void main(String[] args) {
          	SpringApplication.run(MyApplication.class, args);
      	}
      }
      
    • 使用 @Scheduled 注解创建定时任务
      • @Scheduled 注解用于标记一个方法为定时任务。可以通过 cron 表达式、固定延迟(fixedDelay)、固定速率(fixedRate)等方式配置任务的执行时间。
        • Cron 表达式
          • Cron 表达式:是一种灵活的时间配置方式,支持秒、分、时、日、月、周等字段。
            import org.springframework.scheduling.annotation.Scheduled;
            import org.springframework.stereotype.Component;
            @Component
            public class MyScheduledTasks {
            	@Scheduled(cron = "0 * * * * ?") // 每分钟执行一次
            	public void taskWithCron() {
            		System.out.println("Cron 任务执行: " + System.currentTimeMillis());
            	}
            }
            
          • 固定延迟(fixedDelay)
            • fixedDelay:表示任务执行完成后,延迟指定时间再执行下一次任务。
              @Scheduled(fixedDelay = 5000) // 每次任务完成后,延迟 5 秒再执行下一次
              public void taskWithFixedDelay() {
              	System.out.println("FixedDelay 任务执行: " + System.currentTimeMillis());
              }
              
            • 固定速率(fixedRate)
              • fixedRate:表示任务以固定的速率执行,无论上一次任务是否完成。
                @Scheduled(fixedRate = 3000) // 每 3 秒执行一次
                public void taskWithFixedRate() {
                	System.out.println("FixedRate 任务执行: " + System.currentTimeMillis());
                }
                
              • 配置定时任务线程池
                • 创建自定义线程池
                  • Spring Boot 会自动将 @Scheduled 注解的任务绑定到 ThreadPoolTaskScheduler 自定义线程池中。
                    import org.springframework.context.annotation.Bean;
                    import org.springframework.context.annotation.Configuration;
                    import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler;
                    @Configuration
                    public class SchedulerConfig {
                    	@Bean
                    	public ThreadPoolTaskScheduler taskScheduler() {
                        	ThreadPoolTaskScheduler scheduler = new ThreadPoolTaskScheduler();
                        	scheduler.setPoolSize(10); // 设置线程池大小
                        	scheduler.setThreadNamePrefix("MyScheduler-"); // 设置线程名前缀
                        	return scheduler;
                    	}
                    }
                    

二、异步任务

在 Spring Boot 中,实现异步任务非常简单,主要通过 @Async 注解和 TaskExecutor 接口来实现。异步任务适用于需要并发执行的场景,例如发送邮件、处理文件、调用外部 API 等。

  1. 启用异步任务支持

    • 在 Spring Boot 应用中,首先需要启用异步任务支持。可以通过在配置类或主应用类上添加 @EnableAsync 注解来实现。
      import org.springframework.boot.SpringApplication;
      import org.springframework.boot.autoconfigure.SpringBootApplication;
      import org.springframework.scheduling.annotation.EnableAsync;
      @SpringBootApplication
      @EnableAsync // 启用异步任务支持
      public class MyApplication {
      	public static void main(String[] args) {
          	SpringApplication.run(MyApplication.class, args);
      	}
      }
      
    • 使用 @Async 注解创建异步任务

      • @Async 注解用于标记一个方法为异步任务。被标记的方法会在独立的线程中执行。
        import org.springframework.scheduling.annotation.Async;
        import org.springframework.stereotype.Service;
        @Service
        public class MyAsyncService {
        	@Async // 标记为异步方法
        	public void asyncTask() {
            	System.out.println("异步任务开始执行,线程: " + Thread.currentThread().getName());
            	try {
                	Thread.sleep(5000); // 模拟耗时操作
            	} catch (InterruptedException e) {
                	e.printStackTrace();
            	}
            	System.out.println("异步任务执行完成,线程: " + Thread.currentThread().getName());
        	}
        }
        
      • 配置线程池

        • 默认情况下,Spring Boot 使用 SimpleAsyncTaskExecutor 执行异步任务,每次都会创建一个新线程。为了更高效地管理线程,可以配置自定义线程池。
          • 使用 ThreadPoolTaskExecutor 配置线程池
            import org.springframework.context.annotation.Bean;
            import org.springframework.context.annotation.Configuration;
            import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
            import java.util.concurrent.Executor;
            @Configuration
            public class AsyncConfig {
            	@Bean(name = "taskExecutor")
            	public Executor taskExecutor() {
            		ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
            		executor.setCorePoolSize(10); // 核心线程数
            		executor.setMaxPoolSize(20); // 最大线程数
            		executor.setQueueCapacity(50); // 队列容量
            		executor.setThreadNamePrefix("Async-"); // 线程名前缀
            		executor.initialize();
            		return executor;
            	}
            }
            
          • 在 @Async 注解中指定线程池的名称
            @Async("taskExecutor") // 指定线程池
            public void asyncTask() {
            	System.out.println("异步任务执行,线程: " + Thread.currentThread().getName());
            }
            
          • 处理异步任务的返回值

            • 如果异步方法有返回值,可以使用 Future 或 CompletableFuture 来获取结果。
              • 使用 Future,调用方可以通过 Future.get() 方法获取结果
                import org.springframework.scheduling.annotation.Async;
                import org.springframework.stereotype.Service;
                import java.util.concurrent.Future;
                @Service
                public class MyAsyncService {
                	@Async
                	public Future asyncTaskWithReturn() {
                		System.out.println("异步任务开始执行,线程: " + Thread.currentThread().getName());
                		try {
                			Thread.sleep(5000); // 模拟耗时操作
                		} catch (InterruptedException e) {
                			e.printStackTrace();
                		}
                		return new AsyncResult("任务完成");
                	}
                }
                // 调用 MyAsyncService 的异步方法
                Future future = myAsyncService.asyncTaskWithReturn();
                // 阻塞等待结果
                String result = future.get(); 
                
              • 使用 CompletableFuture,Java 8 引入的增强版 Future,支持更灵活的任务编排。
                import org.springframework.scheduling.annotation.Async;
                import org.springframework.stereotype.Service;
                import java.util.concurrent.CompletableFuture;
                @Service
                public class MyAsyncService {
                	@Async
                	public CompletableFuture asyncTaskWithCompletableFuture() {
                		System.out.println("异步任务开始执行,线程: " + Thread.currentThread().getName());
                		try {
                			Thread.sleep(5000); // 模拟耗时操作
                		} catch (InterruptedException e) {
                			e.printStackTrace();
                		}
                		return CompletableFuture.completedFuture("任务完成");
                	}
                }
                CompletableFuture future = myAsyncService.asyncTaskWithCompletableFuture();
                future.thenAccept(result -> System.out.println("任务结果: " + result));
                
              • 异常处理

                • 异步任务中的异常不会传播到调用方,需要通过以下方式处理:
                  • 自定义异常处理器,实现 AsyncUncaughtExceptionHandler 接口,处理未捕获的异常。
                    import org.springframework.aop.interceptor.AsyncUncaughtExceptionHandler;
                    import org.springframework.context.annotation.Configuration;
                    import org.springframework.scheduling.annotation.AsyncConfigurer;
                    import org.springframework.scheduling.annotation.EnableAsync;
                    import java.lang.reflect.Method;
                    import java.util.concurrent.Executor;
                    @Configuration
                    @EnableAsync
                    public class AsyncConfig implements AsyncConfigurer {
                    	@Override
                    	public Executor getAsyncExecutor() {
                    		ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
                    		executor.setCorePoolSize(10);
                    		executor.setMaxPoolSize(20);
                    		executor.setQueueCapacity(50);
                    		executor.setThreadNamePrefix("Async-");
                    		executor.initialize();
                    		return executor;
                    	}
                    	@Override
                    	public AsyncUncaughtExceptionHandler getAsyncUncaughtExceptionHandler() {
                    		return (ex, method, params) -> {
                    			System.err.println("异步任务异常: " + ex.getMessage());
                    			System.err.println("方法: " + method.getName());
                    		};
                    	}
                    }
                    
                  • 在异步方法内部捕获并处理异常。
                    @Async
                    public void asyncTaskWithException() {
                    	try {
                    		// 业务逻辑
                        } catch (Exception e) {
                    		System.err.println("捕获异常: " + e.getMessage());
                    	}
                    }
                    
Spring Boot 定时任务以及异步任务的实现
(图片来源网络,侵删)
Spring Boot 定时任务以及异步任务的实现
(图片来源网络,侵删)
Spring Boot 定时任务以及异步任务的实现
(图片来源网络,侵删)
免责声明:我们致力于保护作者版权,注重分享,被刊用文章因无法核实真实出处,未能及时与作者取得联系,或有版权异议的,请联系管理员,我们会立即处理! 部分文章是来自自研大数据AI进行生成,内容摘自(百度百科,百度知道,头条百科,中国民法典,刑法,牛津词典,新华词典,汉语词典,国家院校,科普平台)等数据,内容仅供学习参考,不准确地方联系删除处理! 图片声明:本站部分配图来自人工智能系统AI生成,觅知网授权图片,PxHere摄影无版权图库和百度,360,搜狗等多加搜索引擎自动关键词搜索配图,如有侵权的图片,请第一时间联系我们。

目录[+]

取消
微信二维码
微信二维码
支付宝二维码