Java学习,一文掌握Java之SpringBoot框架学习文集(4)

在这里插入图片描述

🏆作者简介,普修罗双战士,一直追求不断学习和成长,在技术的道路上持续探索和实践。
🏆多年互联网行业从业经验,历任核心研发工程师,项目技术负责人。
🎉欢迎 👍点赞✍评论⭐收藏

🔎 SpringBoot 领域知识 🔎

链接专栏
SpringBoot 专业知识学习一SpringBoot专栏
SpringBoot 专业知识学习二SpringBoot专栏
SpringBoot 专业知识学习三SpringBoot专栏
SpringBoot 专业知识学习四SpringBoot专栏
SpringBoot 专业知识学习五SpringBoot专栏

文章目录

  • 🏆 学习Java框架之Spring Boot
    • 🔎 Java框架之Spring Boot学习(4)
      • 🍁🍁 01、Spring Boot 中的事务管理方式有哪些?
      • 🍁🍁 02、Spring Boot 如何实现分布式锁?
      • 🍁🍁 03、Spring Boot 中的事件驱动模型是如何实现的?
      • 🍁🍁 04、Spring Boot 中的优雅停机如何实现?
      • 🍁🍁 05、如何使用 Spring Boot 实现单点登录(SSO)?
      • 🍁🍁 06、Spring Boot 中的国际化和本地化支持是如何实现的?
      • 🍁🍁 07、Spring Boot 中如何集成第三方框架或工具?
      • 🍁🍁 08、Spring Boot 如何实现服务注册与发现?
      • 🍁🍁 09、如何在 Spring Boot 中配置连接池和线程池?
      • 🍁🍁 10、Spring Boot 中如何优化应用性能?

🏆 学习Java框架之Spring Boot

🔎 Java框架之Spring Boot学习(4)

🍁🍁 01、Spring Boot 中的事务管理方式有哪些?

在 Spring Boot 中,常用的事务管理方式有如下几种:

1. 声明式事务管理

声明式事务管理是 Spring 的一种传统的事务管理方式,它的实现方式是通过对方法或类进行注解来实现,在需要进行事务管理时,通过 AOP 技术实现对事务进行拦截,在事务范围内执行方法。

在 Spring Boot 中,我们可以通过在方法上添加 @Transactional 注解来开启声明式事务管理,如下所示:

@Service
public class UserServiceImpl implements UserService {

    @Autowired
    private UserDao userDao;

    @Transactional
    @Override
    public void addUser(User user) {
        userDao.save(user);
    }

    @Transactional
    @Override
    public void updateUser(User user) {
        userDao.save(user);
    }

    @Transactional
    @Override
    public void deleteUser(Long userId) {
        userDao.deleteById(userId);
    }
}

2. 编程式事务管理

编程式事务管理是通过编写代码手动控制事务的提交和回滚。在 Spring Boot 中,我们可以通过 TransactionTemplatePlatformTransactionManager 这两个接口来实现编程式事务管理。

下面是一个使用 TransactionTemplate 实现编程式事务管理的示例:

@Service
public class UserServiceImpl implements UserService {

    @Autowired
    private UserDao userDao;
    
    @Autowired
    private TransactionTemplate transactionTemplate;

    @Override
    public void addUser(User user) {
        transactionTemplate.execute(new TransactionCallbackWithoutResult() {
            @Override
            protected void doInTransactionWithoutResult(TransactionStatus status) {
                userDao.save(user);
            }
        });
    }

    @Override
    public void updateUser(User user) {
        transactionTemplate.execute(new TransactionCallbackWithoutResult() {
            @Override
            protected void doInTransactionWithoutResult(TransactionStatus status) {
                userDao.save(user);
            }
        });
    }

    @Override
    public void deleteUser(Long userId) {
        transactionTemplate.execute(new TransactionCallbackWithoutResult() {
            @Override
            protected void doInTransactionWithoutResult(TransactionStatus status) {
                userDao.deleteById(userId);
            }
        });
    }
}

3. JPA 自带的事务管理

对于使用 JPA 实现数据访问的应用程序,可以使用 JPA 自带的事务管理,它的实现方式是在 EntityManager 接口中提供了一个 Transaction 接口,通过该接口实现事务的提交和回滚。在 Spring Boot 中,我们可以使用 @Transactional 注解来开启 JPA 自带的事务管理,如下所示:

@Service
public class UserServiceImpl implements UserService {

    @Autowired
    private UserRepository userRepository;

    @Transactional
    @Override
    public void addUser(User user) {
        userRepository.save(user);
    }

    @Transactional
    @Override
    public void updateUser(User user) {
        userRepository.save(user);
    }

    @Transactional
    @Override
    public void deleteUser(Long userId) {
        userRepository.deleteById(userId);
    }
}

在使用以上三种方式时,均需注意事务的边界,保证数据的一致性和完整性,同时尽可能避免死锁和性能问题。

🍁🍁 02、Spring Boot 如何实现分布式锁?

要在Spring Boot中实现分布式锁,可以使用Redis作为分布式锁的后端存储。下面详细说明实现分布式锁的每一步:

1. 添加Redis依赖:在项目的pom.xml中添加redis依赖,例如:

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>

2. 配置Redis连接信息:在Spring Boot的配置文件(如application.properties或application.yml)中配置Redis的连接信息,包括主机名、端口号、密码等。

3. 创建一个RedisTemplate实例:RedisTemplate是Spring提供的用于操作Redis的工具类。可以通过注解@Autowired将其注入到需要使用的类中。

@Autowired
private RedisTemplate<String, String> redisTemplate;

4. 实现分布式锁的获取方法:在需要获取分布式锁的地方,可以定义一个方法用于获取锁。方法内通过Redis的setIfAbsent方法来设置一个key-value键值对,其中key作为锁的唯一标识,value可以是一个随机生成的唯一值,用于区分不同的线程。如果成功设置了锁,则表示当前线程获取到了锁。

public boolean tryLock(String lockName, String lockValue, long expireTime) {
    Boolean result = redisTemplate.opsForValue().setIfAbsent(lockName, lockValue, expireTime, TimeUnit.MILLISECONDS);
    return result != null && result;
}

5. 实现分布式锁的释放方法:在不需要锁的地方,需要释放分布式锁。可以定义一个方法用于释放锁。方法内通过Redis的del方法删除指定的锁。

public void releaseLock(String lockName) {
    redisTemplate.delete(lockName);
}

以上就是实现分布式锁的详细步骤。需要注意的是,获取锁时使用setIfAbsent方法设置锁的时候应设置过期时间,以防止锁被某个线程长时间占用而无法释放,导致死锁的情况。

🍁🍁 03、Spring Boot 中的事件驱动模型是如何实现的?

在Spring Boot中,事件驱动模型是通过Spring框架的事件机制来实现的。下面是实现事件驱动模型的基本步骤:

1. 创建自定义的事件类:创建一个继承自ApplicationEvent的自定义事件类,该类表示特定的事件。

public class CustomEvent extends ApplicationEvent {
    // 自定义事件的属性和方法
    // ...
}

2. 创建事件发布者:在合适的地方创建一个事件发布者,负责发布事件。

@Component
public class EventPublisher {
    @Autowired
    private ApplicationEventPublisher applicationEventPublisher;

    public void publishEvent(Object source) {
        CustomEvent customEvent = new CustomEvent(source);
        applicationEventPublisher.publishEvent(customEvent);
    }
}

3. 创建事件监听器:创建一个或多个事件监听器,用于处理特定的事件。监听器需要实现ApplicationListener接口,并指定监听的事件类型。

@Component
public class EventListener implements ApplicationListener<CustomEvent> {
    @Override
    public void onApplicationEvent(CustomEvent event) {
        // 处理事件的逻辑
    }
}

4. 接收并处理事件:当事件发布者发布一个事件时,事件监听器会接收到该事件,并执行相应的处理逻辑。

通过上述步骤,Spring Boot实现了事件驱动模型。在应用程序中,当某个事件发生时,使用事件发布者发布该事件,然后事件监听器会监听并处理该事件。这种模型可以实现松耦合的组件之间的通信,使得各个组件可以更加独立和可测试。同时也支持多个监听器同时监听同一个事件,通过事件的机制,实现了解耦和异步处理的能力。

此外,Spring Boot还提供了一些其他的便捷功能,如使用注解@EventListener在方法上直接标注监听事件,以及使用ApplicationEventMulticaster自定义事件的发布和处理方式等。这样,开发者可以根据实际需求选择合适的方式来实现事件驱动模型。

🍁🍁 04、Spring Boot 中的优雅停机如何实现?

Spring Boot中的优雅停机是指在应用关闭时,能够让应用先处理完已有的请求任务,然后再关闭,确保应用退出过程中不会造成任何数据的丢失。下面介绍一下Spring Boot中实现优雅停机的几种方式:

1. 使用Spring Boot的自带功能spring.lifecycle.timeout-per-shutdown-phase,这个属性会在应用退出时给予每个上下文一定时间来执行清理任务。例如,可以在application.properties配置文件中设置:

spring.lifecycle.timeout-per-shutdown-phase=60s

这样,在关闭应用时,Spring Boot会先停止接受请求,等待60秒,然后关闭应用。

2. 自定义中央管理类GracefulShutdownHandler,继承ApplicationListener并实现ContextClosedEvent接口,通过监听ContextClosedEvent 来捕获应用关闭事件,然后通过Thread.sleep()等方式等待当前处理的任务完成。

@Component
public class GracefulShutdownHandler implements ApplicationListener<ContextClosedEvent> {

    private static final Logger log = LoggerFactory.getLogger(GracefulShutdownHandler.class);

    @Autowired
    private WebServerGracefulShutdownHandler webServerGracefulShutdownHandler;

    @Autowired
    private Executor executor;

    @Value("${graceful.shutdown.timeout:30}")
    private int timeoutInSeconds;

    @Override
    public void onApplicationEvent(ContextClosedEvent event) {
        log.info("Graceful shutdown initiated, waiting for active requests to complete");

        // gracefully shut down the embedded web server
        webServerGracefulShutdownHandler.shutdown();

        // wait for tasks to complete
        try {
            concurrentExecutorShutdown(timeoutInSeconds);
        } catch (InterruptedException e) {
            log.info("Interrupted while waiting for tasks to complete", e);
            Thread.currentThread().interrupt();
        }
    }

    private void concurrentExecutorShutdown(int timeout) throws InterruptedException {
        executor.shutdown();
        if(!executor.awaitTermination(timeout, TimeUnit.SECONDS)) {
            log.warn("The executor still has a long running task after {} seconds", timeout);
        }
    }
}

3. 使用Spring Boot Actuator的shutdown端点,可以通过访问http://localhost:port/actuator/shutdown 发送一个POST请求,让应用停止接受新的请求并优雅的关闭,但是要注意需要在application.properties中设置management.endpoint.shutdown.enabled=true开启该功能。

@Configuration
public class CustomActuatorEndpointConfig {

    @Bean
    public ShutdownEndpoint shutdownEndpoint() {
        return new ShutdownEndpoint();
    }

    @Bean
    public GracefulShutdownEndpoint gracefulShutdownEndpoint(GracefulShutdownHandler gracefulShutdownHandler) {
        return new GracefulShutdownEndpoint(gracefulShutdownHandler);
    }

}

通过上述方式,可以简单地实现Spring Boot中的优雅停机,让应用能够更加安全、稳定、不丢数据地停止。

🍁🍁 05、如何使用 Spring Boot 实现单点登录(SSO)?

在Spring Boot中实现单点登录(SSO)可以通过整合Spring Security和Spring Security OAuth2来实现。下面是一种基本的实现方式:

1. 添加依赖:在pom.xml文件中添加Spring Security和Spring Security OAuth2的依赖。

<dependencies>
    <!-- Spring Security -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-security</artifactId>
    </dependency>
    
    <!-- Spring Security OAuth2 -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-oauth2-client</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-oauth2-resource-server</artifactId>
    </dependency>
</dependencies>

2. 配置Spring Security:在application.properties文件中配置Spring Security的相关属性。

# 开启Spring Security
spring.security.oauth2.client.registration.<client-id>.client-id=<client-id>
spring.security.oauth2.client.registration.<client-id>.client-secret=<client-secret>
spring.security.oauth2.client.registration.<client-id>.redirect-uri=<redirect-uri>
spring.security.oauth2.client.registration.<client-id>.client-name=<client-name>
spring.security.oauth2.client.registration.<client-id>.provider=<provider>

其中,<client-id>是你的客户端ID,<client-secret>是你的客户端密钥,<redirect-uri>是登录后重定向的URI,<client-name>是可选的客户端名称,<provider>是提供SSO服务的提供方。

3. 创建登录页面:创建一个登录页面,用于用户进行登录。可以使用Thymeleaf或其他模板引擎来创建页面。

<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8">
    <title>Login</title>
</head>
<body>
    <h2>Login</h2>
    <form th:action="@{/login}" method="post">
        <input type="text" name="username" placeholder="Username" />
        <input type="password" name="password" placeholder="Password" />
        <input type="submit" value="Login" />
    </form>
</body>
</html>

4. 创建资源服务器:创建一个资源服务器,用于验证用户的登录状态和处理受保护的资源。

@Configuration
@EnableResourceServer
public class ResourceServerConfig extends ResourceServerConfigurerAdapter {

    @Override
    public void configure(HttpSecurity http) throws Exception {
        http.authorizeRequests()
            .antMatchers("/", "/login").permitAll()
            .antMatchers("/protected-resource").authenticated();
    }
}

5. 创建回调接口:创建一个回调接口,用于处理成功登录后的回调。

@Controller
public class LoginCallbackController {

    @RequestMapping("/login/callback")
    public String loginCallback() {
        // 处理登录成功后的逻辑
        return "redirect:/protected-resource";
    }
}

以上是一个基本的单点登录(SSO)的实现方式,具体的实现可能会根据具体的需求和业务场景有所变化。此外,还可以根据需要自定义登录页面、认证逻辑和权限控制等。

🍁🍁 06、Spring Boot 中的国际化和本地化支持是如何实现的?

Spring Boot 中的国际化和本地化支持可以通过以下步骤实现:

1. 在 src/main/resources 目录下新建 messages.properties 文件,该文件就是默认的国际化资源文件,里面放置着系统的默认文案。

2. 在 messages.properties 中添加各个需要国际化支持的文本,并为其分配唯一的 key 值,比如:

welcome.msg=欢迎来到 Spring Boot

3. 新建其他语言的本地化资源文件,如 messages_en_US.properties,其中 en_US 代表英语区域,其它的语言区域,参照相关标准修改即可。

4. 在 messages_en_US.properties 中添加与原来的 messages.properties 中对应的国际化文本,比如:

welcome.msg=Welcome to Spring Boot

5. 在需要进行国际化的地方,使用 MessageSource 进行文本的获取,例如:

@Autowired
private MessageSource messageSource;

public String getHello() {
    return messageSource.getMessage("welcome.msg", null, LocaleContextHolder.getLocale());
}

其中,MessageSource 是 Spring 提供的用于获取文本的接口,getMessage() 方法可以根据 key 值获取对应的文本,第二个参数用于传递参数,第三个参数 LocaleContextHolder.getLocale() 方法用于获取当前的语言区域。这样,就可以根据不同的语言区域返回不同的文本内容了。

此外,在 Spring Boot 中,还可以在配置文件中配置国际化文件的基础名称,例如:

spring.messages.basename=messages

这样 Spring Boot 就会自动去寻找 messages.propertiesmessages_en_US.properties 等本地化资源文件,并将其加载到应用中。

总之,Spring Boot 中的国际化和本地化支持非常简单易用,只需要遵循一定的命名规范,并使用 MessageSource 进行文本的获取即可。

🍁🍁 07、Spring Boot 中如何集成第三方框架或工具?

在 Spring Boot 中集成第三方框架或工具通常需要以下几个步骤:

1. 导入依赖:在你的项目的 pom.xml 文件中添加相应的依赖。你可以通过 Maven Central 或其他仓库来查找需要的库的依赖坐标。例如:

<dependencies>
    <!-- 第三方库的依赖 -->
    <dependency>
        <groupId>com.example</groupId>
        <artifactId>example-library</artifactId>
        <version>1.0.0</version>
    </dependency>
</dependencies>

2. 配置和使用:根据第三方框架或工具的要求,进行相应的配置和使用。例如,如果你要集成一个数据库框架,你需要在 application.propertiesapplication.yml 中配置数据库连接信息,然后在你的代码中使用相应的类和方法来操作数据库。

3. 自动配置:Spring Boot 提供了许多自动配置的功能,可以简化第三方框架或工具的集成。如果第三方库符合一些特定的命名约定,Spring Boot 可能会自动为你进行必要的配置。你可以查看 Spring Boot 的官方文档来了解更多关于自动配置的信息。

4. 自定义配置:如果第三方框架或工具的集成需要一些特定的配置信息,你可以在 application.propertiesapplication.yml 中添加相应的配置项,并通过 @Value 注解或 @ConfigurationProperties 注解将其注入到你的代码中。

5. 对接其他组件:有时,你可能还需要对接其他的组件来实现更复杂的功能。你可以使用 Spring Boot 提供的注解、接口或扩展点来与这些组件进行集成。例如,你可以使用 Spring MVC 的 @RestController 注解来定义 RESTful API,或者使用 Spring Security 来添加认证和授权的功能。

这些是集成第三方框架或工具的基本步骤,具体的集成方式和步骤会根据具体的框架或工具而有所不同。建议查阅相关框架或工具的官方文档或示例代码来获取更详细的集成指导。

🍁🍁 08、Spring Boot 如何实现服务注册与发现?

在 Spring Boot 中,你可以使用 Spring Cloud 提供的 Eureka 来实现服务注册与发现。以下是实现步骤:

1. 引入相应的依赖:在你的项目的 pom.xml 文件中添加 Eureka 相关的依赖。例如:

<dependencies>
    <!-- Eureka 依赖 -->
    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
    </dependency>
</dependencies>

2. 配置服务注册中心:在 application.propertiesapplication.yml 中配置 Eureka 服务注册中心的相关信息。例如:

spring:
  application:
    name: service-registry

server:
  port: 8761

eureka:
  client:
    register-with-eureka: false
    fetch-registry: false

这里的 spring.application.name 指定了服务注册中心应用的名称,server.port 指定了服务注册中心的端口号,eureka.client.register-with-eurekaeureka.client.fetch-registry 配置为 false 表示该应用不需要自己注册到其他的服务注册中心,也不需要获取注册中心的服务信息。

3. 启用服务注册中心:在启动类上添加 @EnableEurekaServer 注解来启用服务注册中心。例如:

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer;

@SpringBootApplication
@EnableEurekaServer
public class ServiceRegistryApplication {

    public static void main(String[] args) {
        SpringApplication.run(ServiceRegistryApplication.class, args);
    }
}

4. 配置服务提供者和消费者:对于服务提供者和消费者,你需要添加 spring-cloud-starter-netflix-eureka-client 依赖并配置相应的信息。例如:

spring:
  application:
    name: service-provider

eureka:
  client:
    service-url:
      defaultZone: http://localhost:8761/eureka

spring.application.name 指定了当前服务的名称,eureka.client.service-url.defaultZone 指定了注册中心的地址。

5. 启用服务提供者和消费者:在启动类上添加 @EnableDiscoveryClient 注解来启用服务提供者和消费者。例如:

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;

@SpringBootApplication
@EnableDiscoveryClient
public class ServiceProviderApplication {

    public static void main(String[] args) {
        SpringApplication.run(ServiceProviderApplication.class, args);
    }
}

6. 注册服务、发现服务:在服务提供者中,你可以使用 @RestController@RequestMapping 注解定义 RESTful API,并使用 @EnableDiscoveryClient 注解来将服务注册到 Eureka 服务注册中心。

在服务消费者中,你可以使用 RestTemplate 或者 Feign 等客户端工具来调用其他服务。Spring Cloud 会根据服务注册中心的信息来进行服务发现和负载均衡。

通过以上步骤,你就可以在 Spring Boot 中实现服务注册与发现了。当你的服务提供者启动后,它会向 Eureka 注册中心注册自己的信息。而当服务消费者启动后,它会从 Eureka 注册中心上获取所有可用的服务列表,并通过负载均衡策略调用这些服务。

🍁🍁 09、如何在 Spring Boot 中配置连接池和线程池?

在 Spring Boot 中,你可以使用 Spring Boot Starter JDBC 或 Spring Boot Starter Data JPA 来简化连接池的配置,另外,你可以使用 application.propertiesapplication.yml 来自定义连接池的相关属性。

以下是几种常见的连接池:

1. HikariCP 连接池

HikariCP 是目前性能最好的连接池,它的配置也很简单。在 Spring Boot 中,你只需在 application.propertiesapplication.yml 中定义以下属性:

spring.datasource.hikari.jdbc-url=jdbc:mysql://localhost:3306/test
spring.datasource.hikari.username=root
spring.datasource.hikari.password=root
spring.datasource.hikari.driver-class-name=com.mysql.jdbc.Driver

这样,就启用了 HikariCP 连接池,并通过属性指定了数据库的连接参数。

2. Tomcat JDBC 连接池

Tomcat JDBC 连接池是 Apache Tomcat 项目的一部分,它的配置相对于 HikariCP 来说稍微繁琐一些。你需要在 pom.xml 中添加以下依赖:

<dependency>
    <groupId>org.apache.tomcat</groupId>
    <artifactId>tomcat-jdbc</artifactId>
    <version>${tomcat.version}</version>
</dependency>

其中 ${tomcat.version} 指定 Tomcat 版本号。然后,在 application.propertiesapplication.yml 中添加以下配置信息:

spring.datasource.url=jdbc:mysql://localhost:3306/test
spring.datasource.username=root
spring.datasource.password=password
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
spring.datasource.tomcat.initial-size=5
spring.datasource.tomcat.max-active=20
spring.datasource.tomcat.max-idle=5
spring.datasource.tomcat.min-idle=2
spring.datasource.tomcat.max-wait=10000

这里的 spring.datasource.tomcat 配置项指定了Tomcat JDBC 连接池的相关属性。

3. Druid 连接池

Druid 是一个开源的数据库连接池和 SQL 监控工具,它的配置也比较简单。在 Spring Boot 中,你只需在 application.propertiesapplication.yml 中定义以下属性:

spring.datasource.url=jdbc:mysql://localhost:3306/test
spring.datasource.username=root
spring.datasource.password=root
spring.datasource.driver-class-name=com.mysql.jdbc.Driver

spring.datasource.type=com.alibaba.druid.pool.DruidDataSource
spring.datasource.initial-size=5
spring.datasource.min-idle=5
spring.datasource.max-active=20
spring.datasource.max-wait=60000
spring.datasource.time-between-eviction-runs-millis=60000
spring.datasource.min-evictable-idle-time-millis=300000
spring.datasource.validation-query=SELECT 1 FROM DUAL
spring.datasource.test-while-idle=true
spring.datasource.test-on-borrow=false
spring.datasource.test-on-return=false
spring.datasource.pool-prepared-statements=true
spring.datasource.max-pool-prepared-statement-per-connection-size=20
spring.datasource.filters=stat,wall,log4j
spring.datasource.connection-properties=druid.stat.mergeSql=true;druid.stat.slowSqlMillis=5000

这里的 spring.datasource 配置项指定了 Druid 连接池的相关属性。

关于线程池的使用,你可以使用 Spring 框架自带的 ThreadPoolTaskExecutor 来实现线程池的配置。你可以在配置文件中添加以下属性:

spring.task.execution.pool.max-threads=5
spring.task.execution.pool.queue-capacity=100

这里的 spring.task.execution.pool 配置项指定了线程池的最大线程数和任务队列容量。同时,在代码中,你可以使用 @Async@EnableAsync 注解来使用这个线程池。

下面是一个使用Java实现线程池的简单示例代码:

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class ThreadPoolExample {
    public static void main(String[] args) {
        // 创建线程池,设置最大线程数为3
        ExecutorService executor = Executors.newFixedThreadPool(3);
        
        // 提交任务给线程池
        executor.submit(new Task("Task 1"));
        executor.submit(new Task("Task 2"));
        executor.submit(new Task("Task 3"));

        // 关闭线程池
        executor.shutdown();
    }

    // 定义要执行的任务
    static class Task implements Runnable {
        private final String message;

        public Task(String message) {
            this.message = message;
        }

        @Override
        public void run() {
            System.out.println("Executing task: " + message);
        }
    }
}

上述代码使用了Java的java.util.concurrent包提供的ExecutorService接口和Executors工具类来创建和管理线程池。

通过Executors.newFixedThreadPool(3)创建一个固定线程数为3的线程池。

然后使用executor.submit(new Task("Task x"))方法来向线程池提交任务,这里提交了三个任务。

最后,调用executor.shutdown()方法关闭线程池。注意,关闭线程池后将不再接受新的任务提交,但会等待已提交的任务完成执行。

🍁🍁 10、Spring Boot 中如何优化应用性能?

Spring Boot中可以采用如下几种方式来优化应用性能:

1. 使用缓存:缓存是提高应用性能的重要手段,可以使用Spring Cache来实现缓存的配置和管理。

2. 使用异步调用:异步处理对于一些IO密集型操作,可以有效提高应用的吞吐量和性能。Spring提供了@Async注解来支持异步方法调用。

3. 使用线程池:线程池可以避免频繁的线程创建和销毁,提高线程的复用率,从而提高应用的性能。可以使用ThreadPoolTaskExecutor类来创建线程池。

4. 数据库连接池的优化:可以使用HikariCP、Druid等连接池来优化数据库连接处理的性能。

5. 调整应用配置:例如调整最小、最大线程数、线程池队列容量等参数,调整JVM内存配置等,都可以影响应用的性能表现。

6. 使用缓存数据查询:使用缓存数据查询可以避免频繁的数据库查询操作,从而减少响应时间,并避免数据库负载过大。

7. 使用性能优化工具:比如JProfiler、VisualVM等工具可以用于查看应用中的性能瓶颈和问题,并提供相应的解决方案。

需要注意的是,具体应该采取哪些方式来优化应用性能,需要根据实际情况进行权衡和选择,以取得最好的性能表现。

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/311799.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

GBASE南大通用SQL API 中的 SQL

ESQL 产品为GBASE南大通用数据库 GBase 8s SQL API&#xff08;应用程序编程接口&#xff09;。 GBase 为 C 编程语言产生 SQL API。 下图展示 SQL API 产品如何工作。您编写您在其中将 SQL 语句处理作为可执行代码的源 程序。嵌入式 SQL 预处理器处理您的源程序&#xff0c;它…

【QML COOK】- 008-自定义属性

前面介绍了用C定义QML类型&#xff0c;通常在使用Qt Quick开发项目时&#xff0c;C定义后端数据类型&#xff0c;前端则完全使用QML实现。而QML类型或Qt Quick中的类型时不免需要为对象增加一些属性&#xff0c;本篇就来介绍如何自定义属性。 1. 创建项目&#xff0c;并编辑Ma…

Qt 6之六:Qt Designer介绍

Qt 6之六&#xff1a;Qt Designer介绍 Qt Designer是一个可视化的用户界面设计工具&#xff0c;用于创建Qt应用程序的用户界面&#xff0c;允许开发人员通过拖放和布局来设计和创建GUI界面。 Qt 6之一&#xff1a;简介、安装与简单使用 https://blog.csdn.net/cnds123/articl…

作用域与作用域链

作用域与作用域链 一、什么是作用域 作用域就是一个独立的代码区域&#xff0c;域内的变量不会暴露到外部&#xff0c;外部无法访问&#xff0c;也就是说具有隔离性。 function outFun() {var inVariable "内层变量2"; } outFun(); // inVariable 的作用域仅在函…

matlab绘图修改坐标轴数字字体大小及坐标轴自定义间隔设置

一、背景 在matlab使用plot函数绘图后&#xff0c;生成的图片坐标轴数字字体大小及间隔可能并不符合我们的要求&#xff0c;因此需要自定义修改&#xff0c;具体方法如下 二、修改坐标轴数字字体大小 只需添加以下命令即可&#xff1a; set(gca,FontName,Times New Roman,F…

echarts -- 柱状图之柱状条如何显示白色侧阴影且鼠标移入时高亮

有个图表是要求柱状条的右下侧显示一个白色的侧阴影&#xff0c;一直没找到合适的方法&#xff0c; 加border或者shadowColor都达不到需求的效果。 因为柱状图 中series里可以包含多组数据&#xff0c;有几组就代表一个系列中有几个数据。这就代表series里要写七组数据。 对于上…

你了解计算机网络的发展历史吗?

1.什么是计算机网络 计算机网络是指将一群具有独立功能的计算机通过通信设备以及传输媒体被互联起来的&#xff0c;在通信软件的支持下&#xff0c;实现计算机间资源共享、信息交换或协同工作的系统。计算机网络是计算机技术与通信技术紧密结合的产物&#xff0c;两者的迅速发展…

电阻如何读取阻值

前言&#xff1a;大家经常见到的贴片电阻上的丝印有纯数字、数字与R组合、数字与除R之外的字母组合的&#xff0c;但大家知不知道这样的标注与贴片电阻的i精度相关&#xff1f;同一个阻值因为精度不同&#xff0c;标注也会不同。例如封装为0805的贴片电阻&#xff0c;丝印473和…

STL-list的使用简介

目录 ​编辑 一、list的底层实现是带头双向循环链表 二、list的使用 1、4种构造函数&#xff08;与vector类似&#xff09;​编辑 2、迭代器iterator 3、容量&#xff08;capicity&#xff09;操作 4、element access 元素获取 5、增删查改 list modifiers 6、list的迭…

【计算机组成原理】-指令系统

&#x1f3b5;1.指令的发展 &#x1f308;1.1基础概念 计算机的程序是由一系列的机器指令组成的。指令就是要计算机执行某种操作的命令。从计算机的层次结构来说&#xff0c;有微指令&#xff0c;机器指令和宏指令之分。微程序中用到微指令&#xff0c;属于硬件&#xff0c;而…

Fluids —— MicroSolvers DOP

目录 Gas SubStep —— 重复执行对应的子步 Switch Solver —— 切换解算器 Gas Attribute Swap —— 交换、复制或移动几何体属性 Gas Intermittent Solve —— 固定时间间隔计算子解算器 Gas External Forces —— 计算外部力并更新速度或速度场 Gas Particle Separate…

D3121是什么?主要有哪些特点呢?为什么可以应用在车载音响系统上

D3121 是一块对地能动冲放大器集成电路&#xff0c;该电路能有效消除由线 路电阻所引起的问题及噪声。所需外围电容小&#xff0c;便于设计时小型化的同 时可靠性不降低。广泛应用于车载音响系统内。 D3121 系列采用 DIP8 、 SOP8 、 SIP8 的封装形式封装。 主要特点&#…

面试算法115:重建序列

题目 长度为n的数组org是数字1&#xff5e;n的一个排列&#xff0c;seqs是若干序列&#xff0c;请判断数组org是否为可以由seqs重建的唯一序列。重建的序列是指seqs所有序列的最短公共超序列&#xff0c;即seqs中的任意序列都是该序列的子序列。 例如&#xff0c;如果数组org为…

python绘制热力图-数据处理-VOC数据类别标签分布及数量统计(附代码)

前言 当你需要统计训练数据中每个类别标签有多少&#xff0c;并且想知道坐标中心分布在图像的位置信息时&#xff0c;你可以利用一下脚本进行计算&#xff01; 步骤 要绘制热力图来分析VOC数据的分布统计&#xff0c;可以按照以下步骤进行&#xff1a; 数据处理&#xff1…

移动通信系统关键技术多址接入MIMO学习(8)

1.Multiple-antenna Techniques多天线技术MIMO&#xff0c;从SISO到SIMO到MISO到如今的MIMO&#xff1b; 2.SIMO单发多收&#xff0c;分为选择合并、增益合并&#xff1b;SIMO&#xff0c;基站通过两路路径将信号发送到终端&#xff0c;因为终端接收到的两路信号都是来自同一天…

计算机速成课Crash Course - 18. 操作系统

今天继续计算机速成课Crash Course的系列讲解。 更多技术文章&#xff0c;全网首发公众号 “摸鱼IT” 锁定 -上午11点 - &#xff0c;感谢大家关注、转发、点赞&#xff01; 计算机速成课Crash Course - 17. 集成电路&摩尔定律 18. 操作系统 1940,1950 年代的电脑&#…

rime中州韵小狼毫 词组注释 滤镜

在rime中州韵小狼毫 联想词组 滤镜一文中&#xff0c;我们通过Filter滤镜功能配置了联想词组的功能&#xff0c;这使得我们在输入一些关键词汇时&#xff0c;可以联想补充一些附加的词组&#xff0c;例如我输入“手机”&#xff0c;就可以联想补充对应的手机号&#xff0c;如下…

Kali Linux —— 漏洞分析工具

Cisco-torch与Global Exploiter专攻Cisco漏洞 一、Cisco 工具 Kali 有许多工具&#xff0c;比如信息收集工具、密码爆破工具等等&#xff0c;还有一些可用于攻击 Cisco 路由器的工具。Cisco-torch就是这样&#xff0c;用于大规模扫描、指纹识别和利用的工具之一。 打开终端控…

关于CAD导入**地球的一些问题讨论

先上示例: 上图是将北京王佐停车场的红线CAD图导入到图新地球效果,如果看官正是需要这样的效果,那么请你继续往下看,全是干货! 在地球中导入CAD图可以做为电子沙盘。对于工程人来说,是极有帮助的。以前一直用谷歌地球,大约在2020年左右,就被和谐了。当时感觉挺可惜的。…

[渗透测试学习] Surveillance -HackTheBox

文章目录 信息搜集getshell提权信息搜集 nmap扫描端口 nmap -sV -sC -v -p- --min-rate 1000 10.10.11.245扫出来两个端口,其中80端口有http服务并且重定向到surveillance.htb 那么我们添加下域名然后访问80端口,发现是企业网站尝试扫描子域名和目录无果后,用Wappalyzer插…