SpringBoot自定义线程池

发布时间:2023-05-16

一、SpringBoot自定义线程池最多多少

线程池的大小是由应用程序负责创建的任务决定的。用不太科学的方法来设置线程池的大小,可能会导致应用程序出现各种问题和运行瓶颈。在Springboot中,线程池的大小可能会影响应用程序的吞吐量和可伸缩性。 在Thread类中,在构造函数中提供了一个参数,可以指定线程池最大线程数。该变量名是MAX_THREADS。在Springboot中,我们可以在配置文件中通过设置spring.task.execution.pool.max-threads属性来设置线程池的大小。

@Configuration
@EnableAsync
public class AsyncConfig implements AsyncConfigurer {
  @Override
  public Executor getAsyncExecutor() {
    ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
    executor.setCorePoolSize(2);
    executor.setMaxPoolSize(100);
    executor.setQueueCapacity(5);
    executor.setThreadNamePrefix("CustomThreadpoolDemo");
    executor.initialize();
    return executor;
  }
}

二、SpringBoot自定义线程池异常

当线程池出现异常或线程池中的任务执行出现异常时,我们可以使用异常处理程序捕获和处理异常。 Springboot内置了一个线程池异常处理程序,在发生未捕获异常时,将自动使用该处理程序。可以为ThreadPoolTaskExecutor指定一个AsyncUncaughtExceptionHandler,以便在发生异常时向处理程序发送信息。

@Configuration
@EnableAsync
public class AsyncConfigWithExceptionHandler implements AsyncConfigurer {
  @Override
  public Executor getAsyncExecutor() {
    ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
    executor.setCorePoolSize(2);
    executor.setMaxPoolSize(100);
    executor.setQueueCapacity(5);
    executor.setThreadNamePrefix("CustomThreadpoolDemo");
    executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
    executor.initialize();
    return executor;
  }
  @Override
  public AsyncUncaughtExceptionHandler getAsyncUncaughtExceptionHandler() {
    return new CustomAsyncExceptionHandler();
  }
  private static class CustomAsyncExceptionHandler implements AsyncUncaughtExceptionHandler {
    @Override
    public void handleUncaughtException(Throwable ex, Method method, Object... params) {
      log.error("Exception message - " + ex.getMessage());
      log.error("Method name - " + method.getName());
      for (Object param : params) {
        log.error("Parameter value - " + param);
      }
    }
  }
}

三、SpringBoot自定义线程池无效

在Springboot中,初学者可能会遇到线程池无效的问题。如果在应用程序中配置了线程池,则只有使用@Async注释的方法才可以在其中运行。设置了线程池时,Springboot会尝试在其中查询该注释的方法,并调用其中方法的副本。 在使用Springboot自定义线程池的方法上添加@Async注解,以使该方法在配置的线程池中运行。如果没有注入线程池,则可能会调用原始方法。

@Service
public class UserServiceImpl implements UserService {
  @Autowired
  private UserRepository userRepository;
  @Autowired
  private NumberService numberService;
  @Override
  @Async("customAsyncExecutor")
  public CompletableFuture<User> findById(Long id) {
    User user = userRepository.findById(id).orElse(null);
    int randomNumber = numberService.generateRandomNumber();
    user.setRandomNumber(randomNumber);
    return CompletableFuture.completedFuture(user);
  }
}

四、SpringBoot自定义线程池异步执行

在Springboot中,异步执行非常常见,并且可以通过简单地使用@Async注解来实现。使用@Async注解的方法在后台线程池中运行,并立即返回,而不必等待方法返回。

@Service
public class NotificationServiceImpl implements NotificationService {
  @Async("emailSendPool")
  @Override
  public CompletableFuture<String> sendEmailNotification(String email, String message) {
    log.info("Send email to " + email);
    //send email logic
    return CompletableFuture.completedFuture("Email sent successfully to " + email);
  }
  @Async("smsSendPool")
  @Override
  public CompletableFuture<String> sendSmsNotification(String phoneNumber, String message) {
    log.info("Send sms to " + phoneNumber);
    //send sms logic
    return CompletableFuture.completedFuture("SMS sent successfully to " + phoneNumber);
  }
}

五、基于SpringBoot自定义线程池

基于Springboot自定义线程池可以帮助应用程序实现异步事件处理。除了使用@Async注解外,还可以使用Springboot的基于事件的编程模型来自定义异步操作。

@Component
public class CartEventListener {
  @Async("cartStateChangePool")
  @EventListener
  public void cartChangeListener(ShoppingCartStateChangedEvent event) {
    //perform cart state change logic
    log.info("Shopping Cart state changed: " + event.getShoppingCart().getState());
  }
}

六、@Async自定义线程池

Springboot的@Async注解可以使用自定义线程池来调用应用程序的异步方法。使用@Async时,如果未提供自定义执行器,则会使用默认线程池。

@Configuration
@EnableAsync
public class AsyncConfig {
  @Bean("customAsyncExecutor")
  public Executor customAsyncExecutor() {
    ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
    executor.setCorePoolSize(2);
    executor.setMaxPoolSize(100);
    executor.setQueueCapacity(5);
    executor.setThreadNamePrefix("CustomThreadpoolDemo");
    executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
    executor.initialize();
    return executor;
  }
}

七、CompleteFuture自定义线程池

使用CompleteFuture可以帮助我们编写更清晰,更简单且更易于扩展的代码,因为我们可以利用CompleteFuture的方法链将片段组合在一起。

@Service
public class OrderServiceImpl implements OrderService {
  @Autowired
  private UserService userService;
  @Autowired
  private ProductService productService;
  @Async("customAsyncExecutor")
  @Override
  public CompletableFuture<Order> placeOrder(Long userId, Long productId) {
    CompletableFuture<User> userFuture = userService.findById(userId);
    CompletableFuture<Product> productFuture = productService.findById(productId);
    return userFuture.thenCombine(productFuture, (user, product) -> {
        Order order = new Order();
        order.setUser(user);
        order.setProduct(product);
        order.setOrderDate(LocalDateTime.now());
        return order;
    });
  }
}

八、自定义线程池7个参数

在Springboot中,使用ThreadPoolTaskExecutor可以自定义线程池。可以通过以下七个参数设置线程池:

  1. corePoolSize:线程池的大小(默认情况下5)
  2. maxPoolSize:线程池的最大大小(默认情况下10)
  3. queueCapacity:队列大小(默认情况下100)
  4. keepAliveTime:线程池的线程保持活动的时间(默认情况下60s)
  5. threadNamePrefix:每个线程的名称前缀(默认情况下“thread”)
  6. rejectedExecutionHandler:拒绝策略(默认情况下使用ThreadPoolExecutor.CallerRunsPolicy)
  7. allowCoreThreadTimeout:是否允许核心线程在空闲时间超过keepAliveTime时被回收(默认情况下为false)
@Configuration
@EnableAsync
public class AsyncConfig {
  @Bean("customAsyncExecutor")
  public ThreadPoolTaskExecutor customAsyncExecutor() {
    ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
    executor.setCorePoolSize(2);
    executor.setMaxPoolSize(100);
    executor.setQueueCapacity(5);
    executor.setThreadNamePrefix("CustomThreadpoolDemo");
    executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
    executor.initialize();
    return executor;
  }
}