java面试场景问题
还在补充,这几天工作忙,闲了会把答案附上去,也欢迎各位大佬评论区讨论
1.不用分布式锁如何防重复提交
方法 1:基于唯一请求 ID(幂等 Token)
思路:前端生成 一个唯一的 requestId(如 UUID或者能表示本次请求的唯一标识字段),每次提交请求时带上它。
后端使用 Redis存储 requestId,如果已经存在,则拒绝处理。
实现:前端:每次提交请求时,生成一个 requestId:
javascript
const requestId = crypto.randomUUID(); // 生成唯一 ID
axios.post('/api/submit', { data, requestId });
后端java
@Autowired
private StringRedisTemplate redisTemplate;public ResponseEntity<String> submitRequest(String requestId, Data data) {Boolean isDuplicate = redisTemplate.opsForValue().setIfAbsent("request:" + requestId, "1", 10, TimeUnit.MINUTES);if (Boolean.FALSE.equals(isDuplicate)) {return ResponseEntity.status(HttpStatus.CONFLICT).body("重复提交");}try {// 处理业务逻辑process(data);return ResponseEntity.ok("提交成功");} finally {redisTemplate.delete("request:" + requestId); // 可选:若确保幂等性,可不删除}
}
优点: ✅ 适用于分布式系统
✅ 性能好(基于 Redis 操作)
✅ Token 过期时间 防止长期占用
方法 2:数据库唯一索引
思路:让数据库的唯一索引防止重复提交,常用于订单号、业务唯一键。
实现
数据库表添加唯一索引:
sql
ALTER TABLE orders ADD UNIQUE (order_no);
后端插入数据:
try {orderMapper.insert(order);
} catch (DuplicateKeyException e) {return ResponseEntity.status(HttpStatus.CONFLICT).body("重复提交");
}
优点: ✅ 数据库级防重,最可靠
✅ 适合订单、支付等业务场景
⛔ 性能受限于数据库,高并发需优化
方法 3:前端按钮防抖
思路:提交后禁用按钮,直到返回响应,防止用户快速点击。
实现
document.getElementById("submit-btn").addEventListener("click", function() {this.disabled = true; // 禁用按钮axios.post('/api/submit', { data }).then(response => alert(response.data)).finally(() => this.disabled = false); // 请求完成后恢复
});
优点: ✅ 简单易行,无需改后端
⛔ 前端可绕过,不适用于高安全性场景
方法 4:悲观锁(数据库行锁)
思路:通过 SELECT … FOR UPDATE 加行锁,确保事务内数据不会被其他请求修改。
实现
@Transactional
public void submitOrder(Long orderId) {Order order = orderMapper.selectByIdForUpdate(orderId); // 加锁if (order.getStatus() != OrderStatus.PENDING) {throw new IllegalStateException("订单已处理");}order.setStatus(OrderStatus.PROCESSED);orderMapper.updateById(order);
}
优点: ✅ 确保单线程执行,避免重复
⛔ 数据库性能受影响,不适用于高并发
总结
)
推荐方案:
高并发系统:幂等 Token + Redis ✅
数据库事务业务:唯一索引 / 状态机 ✅
简单防重:前端按钮防抖 ✅
如果并发压力大,可以结合多种方案,例如:
Redis 幂等 Token + 数据库唯一索引 🚀
前端防抖 + 后端幂等 Token 🔥
2.redis的哨兵模式是如何选举的
Redis 的哨兵模式(Sentinel)用于监控 Redis 服务器,并在主服务器(Master)宕机时自动执行故障转移(Failover)。哨兵模式的选举过程主要发生在主服务器不可用时,选举一个新的主服务器。以下是选举的具体步骤:
- 发现主服务器故障
每个哨兵(Sentinel)会定期向主服务器和从服务器发送 PING 命令,检查它们的状态。
如果多个哨兵在 down-after-milliseconds 时间内没有收到主服务器的响应,就会认为它 主观下线(Subjectively Down, sDown)。
当 大多数 哨兵都认定主服务器宕机时,主服务器就会进入 客观下线(Objectively Down, oDown) 状态,触发故障转移。 - 哨兵选举领导者
当主服务器 oDown 后,需要一个哨兵来执行故障转移,因此哨兵之间需要进行 Raft 算法 类似的选举流程:
所有哨兵都可以参与选举,尝试成为领导者(Leader)。
每个哨兵向其他哨兵发送 SENTINEL is-master-down-by-addr 请求,询问它们是否同意自己成为领导者。
其他哨兵如果还没有投票,则会同意投票给该请求的哨兵。
如果一个哨兵获得超过一半的票数(多数派),就会成为领导者。
3. 选择新的主服务器
领导者哨兵会从现有的从服务器中选择一个最合适的来提升为新的主服务器:
选择 复制进度最接近主服务器 的从服务器(偏移量最大)。
如果多个从服务器复制进度相同,选择 ID 最小 的。
如果没有合适的从服务器,则失败,等待下一轮选举。
4. 执行故障转移
领导者哨兵发送 slaveof no one 命令,让选中的从服务器成为新的主服务器。
让其他从服务器执行 slaveof <new_master>,将它们的主服务器指向新的主服务器。
更新配置信息,广播新的主服务器地址给所有 Redis 客户端。
5. 恢复监控
整个集群稳定后,哨兵继续监控新的主服务器和从服务器,准备处理下一次故障。
通过这种选举机制,Redis 的哨兵模式能够自动检测主服务器故障,并确保集群能够继续运行。
3.线程池的原理
-
线程池的概念
线程池(Thread Pool)是一种用于管理和复用线程的技术,它维护了一组可复用的线程,避免了频繁创建和销毁线程的开销,从而提高程序的执行效率。 -
线程池的核心组成
线程池主要由以下几个核心部分组成:
线程队列(BlockingQueue)
用于存放等待执行的任务。常见的队列类型:
无界队列(LinkedBlockingQueue):适用于任务量大但不会超出系统资源的情况。
有界队列(ArrayBlockingQueue):适用于控制任务数量,防止资源耗尽。
优先队列(PriorityBlockingQueue):任务可根据优先级执行。
核心线程数(Core Pool Size)
线程池初始化后,线程数不超过核心线程数时,即使空闲,也不会销毁。
最大线程数(Maximum Pool Size)
当任务数量超过核心线程数时,线程池可以临时创建额外的线程,但不会超过最大线程数。
任务拒绝策略(Rejection Policy)
当线程池达到最大线程数且任务队列已满时,新任务将被拒绝。常见策略:
AbortPolicy(默认):抛出异常。
CallerRunsPolicy:调用线程自己执行任务,降低任务提交速率。
DiscardPolicy:直接丢弃任务,不处理也不抛出异常。
DiscardOldestPolicy:丢弃队列中最早的任务,再尝试执行新任务。
线程工厂(ThreadFactory)
用于创建线程,可以自定义线程命名、设置守护线程等。
存活时间(Keep Alive Time)
当线程数超过核心线程数时,多余的空闲线程会在超过该时间后被销毁。
3. 线程池的工作流程
任务提交到线程池。
如果当前运行线程数小于核心线程数,直接创建新线程执行任务。
如果核心线程数已满,则任务进入队列等待。
若队列已满且线程数小于最大线程数,则创建新线程执行任务。
若线程数达到最大值且任务队列也满了,则触发任务拒绝策略。
线程执行完任务后,若线程数超过核心线程数,多余的空闲线程会在 keepAliveTime 超过后被销毁。
4. 线程池的优点
提高性能:减少线程创建和销毁的开销。
提高资源利用率:合理分配线程,避免资源浪费。
控制并发:防止创建过多线程导致系统资源耗尽。
5. 线程池的应用
在 Java 中,ExecutorService 提供了常见的线程池实现:
ExecutorService executor = Executors.newFixedThreadPool(5);
executor.submit(() -> {System.out.println("任务执行:" + Thread.currentThread().getName());
});
executor.shutdown();
- 自定义线程池
使用 ThreadPoolExecutor 自定义线程池:
ExecutorService threadPool = new ThreadPoolExecutor(2, // 核心线程数5, // 最大线程数60, // 线程空闲存活时间TimeUnit.SECONDS, // 时间单位new LinkedBlockingQueue<>(10), // 任务队列Executors.defaultThreadFactory(), // 线程工厂new ThreadPoolExecutor.AbortPolicy() // 拒绝策略
);
4.spring的spi和dubbo的spi机制是什么?
Spring 的 SPI(Service Provider Interface) 主要基于 Java 原生的 java.util.ServiceLoader 机制,并在此基础上进行了增强。它主要用于加载和扩展 Spring 组件,如 SpringFactoriesLoader。
1. Java SPI 机制
Java 提供 java.util.ServiceLoader,用于加载 META-INF/services/ 目录下的服务配置文件。
这个配置文件的命名规则是接口的全限定名,内容是具体的实现类。
示例
定义 SPI 接口
public interface MyService {void execute();
}//提供实现
public class MyServiceImpl implements MyService {@Overridepublic void execute() {System.out.println("MyServiceImpl executed");}
}
在 META-INF/services/ 目录下,创建文件 com.example.MyService,内容如下:
com.example.MyServiceImpl
使用 ServiceLoader 进行加载:
ServiceLoader<MyService> loader = ServiceLoader.load(MyService.class);
for (MyService service : loader) {service.execute();
}
2. Spring 的 SPI
Spring 在 Java SPI 机制基础上,增加了 SpringFactoriesLoader,用于从 META-INF/spring.factories 文件中加载扩展组件。
Spring SPI 加载方式:
主要通过 org.springframework.core.io.support.SpringFactoriesLoader 进行加载。
读取 META-INF/spring.factories 配置文件,该文件的内容格式为:
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
com.example.MyAutoConfiguration
在 Spring Boot 自动装配(AutoConfiguration)中,大量使用了该机制。
示例
1.在 spring.factories 文件中配置:
org.springframework.boot.autoconfigure.EnableAutoConfiguration=com.example.MyAutoConfiguration
2.MyAutoConfiguration 类:
@Configuration
public class MyAutoConfiguration {@Beanpublic MyService myService() {return new MyServiceImpl();}
}
3.Spring Boot 在启动时,会通过 SpringFactoriesLoader.loadFactoryNames(EnableAutoConfiguration.class, classLoader) 自动加载 MyAutoConfiguration 类,从而完成自动配置。
3.Dubbo 的 SPI 机制
Dubbo 也使用了 SPI 机制,但相比 Java SPI 进行了增强,主要特点包括:
自定义 SPI 机制:Dubbo 提供了 ExtensionLoader,替代 Java 的 ServiceLoader,支持 AOP、IoC 和自适应扩展等功能。
META-INF/dubbo/ 目录:Dubbo 的 SPI 机制约定配置文件放在 META-INF/dubbo/ 或 META-INF/services/ 目录下。
@SPI 注解:Dubbo 允许在接口上使用 @SPI 进行标注,指明默认实现。
支持 @Adaptive 注解:Dubbo 支持自适应扩展,能够根据参数动态选择实现类。
- Dubbo SPI 使用方式
1>定义 SPI 接口
import org.apache.dubbo.common.extension.SPI;@SPI("defaultImpl") // 指定默认实现
public interface MyService {void execute();
}
2>提供多个实现
public class DefaultImpl implements MyService {@Overridepublic void execute() {System.out.println("Executing Default Implementation");}
}public class AdvancedImpl implements MyService {@Overridepublic void execute() {System.out.println("Executing Advanced Implementation");}
}
3>配置 META-INF/dubbo/com.example.MyService
defaultImpl=com.example.DefaultImpl
advancedImpl=com.example.AdvancedImpl
4>通过 Dubbo 的 ExtensionLoader 加载
ExtensionLoader<MyService> loader = ExtensionLoader.getExtensionLoader(MyService.class);
MyService service = loader.getDefaultExtension(); // 获取默认实现
service.execute();MyService advancedService = loader.getExtension("advancedImpl"); // 获取指定实现
advancedService.execute();
- Dubbo SPI 的增强点
默认实现:@SPI(“defaultImpl”) 指定默认实现。
自动注入:Dubbo 的扩展点支持 IoC,可以自动注入依赖。
自适应扩展:@Adaptive 允许根据运行时参数动态选择实现。
Wrapper 扩展:支持 AOP 方式的扩展,如日志增强。
总结
Spring SPI 主要用于 Spring Boot 自动装配。
Dubbo SPI 主要用于服务扩展,提供了更强的动态适配能力。
Dubbo SPI 机制在性能、可扩展性和动态适应方面,比 Spring 和 Java SPI 机制更加强大。
5.流量激增,大批量数据如何处理?
- 数据分片与分区
数据库分片(Sharding):将数据拆分到多个数据库实例上,减少单个数据库的压力。
分区表(Partitioning):对大表进行分区存储,提高查询性能,例如按时间、地域等划分。 - 高效的缓存策略
CDN(内容分发网络):对于静态资源(图片、视频、文件等),使用CDN分发可减少源站压力。
Redis/Memcached:对于热点数据,将查询结果缓存,减少数据库访问次数。
本地缓存:在应用层使用LRU缓存避免频繁访问远程存储。 - 异步处理与消息队列
消息队列(Kafka、RabbitMQ、RocketMQ):削峰填谷,将高并发请求转换为异步任务,提高吞吐量。
任务队列(Celery、Sidekiq):对于非实时数据处理(如日志分析、统计计算),可以异步执行。 - 扩展架构
水平扩展(Scale Out):增加服务器数量,通过负载均衡(Nginx、HAProxy)分发流量。
垂直扩展(Scale Up):提升单机性能,如升级CPU、内存、磁盘IO能力。 - 数据流处理
流式计算(Flink、Spark Streaming、Storm):用于实时数据处理,避免批量计算的延迟问题。
批处理(Hadoop、Spark):适用于大规模离线分析任务。 - 数据库优化
索引优化:合理使用B+树索引、哈希索引等加速查询。
SQL优化:避免N+1查询,使用JOIN优化查询结构。
读写分离:主从数据库架构,分离读写操作,提高查询性能。 - 日志及监控
ELK(Elasticsearch + Logstash + Kibana):用于日志分析,监测异常流量。
Prometheus + Grafana:监控系统状态,及时发现瓶颈。
通过以上策略,可以高效应对流量激增和大批量数据处理,提高系统稳定性和响应速度。
6.rabbitmq如何防止重复消费,高并发情况下
- 确保手动 ACK
避免使用自动 ACK,确保消息处理完毕后再确认
✅ 正确做法(手动 ACK)
channel.basicConsume(QUEUE_NAME, false, new DefaultConsumer(channel) {@Overridepublic void handleDelivery(String consumerTag, Envelope envelope,AMQP.BasicProperties properties, byte[] body) throws IOException {try {String message = new String(body, "UTF-8");processMessage(message); // 处理消息// 处理完成后手动确认channel.basicAck(envelope.getDeliveryTag(), false);} catch (Exception e) {// 处理失败,拒绝消息并重新放回队列channel.basicNack(envelope.getDeliveryTag(), false, true);}}
});
📌 说明
autoAck=false (手动 ACK)
basicAck() (成功后确认消息已处理)
basicNack() (失败后重新入队)
- 业务层去重
即使 RabbitMQ 保障**“至少一次”(At Least Once)**投递,仍可能发生重复消费,因此需要在业务层去重。
✅ 方法 1:数据库唯一约束
可以使用数据库的唯一索引字段,如订单号 order_id:
INSERT INTO orders (order_id, user_id, amount)
VALUES ('msg_123456', 'user_001', 100)
ON DUPLICATE KEY UPDATE order_id=order_id;
如果 order_id 已存在,则不会插入新的记录。
✅ 方法 2:Redis 去重
使用 Redis SETNX(防止短时间内重复处理)
public boolean isProcessed(String messageId) {String key = "msg_" + messageId;Boolean success = redisTemplate.opsForValue().setIfAbsent(key, "1", 60, TimeUnit.SECONDS);return success != null && !success;
}public void processMessage(String message) {if (isProcessed(message)) {System.out.println("消息已处理,跳过: " + message);return;}// 业务逻辑处理
}
- 设置消息 TTL + 死信队列(DLX)
防止重复消费时死循环
✅ 设置消息 TTL
Map<String, Object> args = new HashMap<>();
args.put("x-message-ttl", 60000); // 60s 后消息过期
args.put("x-dead-letter-exchange", "dlx_exchange"); // 指定死信交换机
channel.queueDeclare("task_queue", true, false, false, args);
✅ 死信队列(DLX)
当消息失败多次后,可以转移到死信队列,避免重复消费:
args.put("x-dead-letter-routing-key", "dlx_routing_key");
- 限制消费者并发数
如果消费者并发过高,可能会导致 RabbitMQ 消息重复投递,可以限制每个消费者最多只能预取 1 条消息:
channel.basicQos(1); // 每个消费者一次只处理 1 条消息
- 生产者端消息确认
RabbitMQ 提供 Confirm 机制,确保消息不会丢失
channel.confirmSelect(); // 开启发布确认模式channel.basicPublish("", "task_queue", MessageProperties.PERSISTENT_TEXT_PLAIN, message.getBytes("UTF-8"));// 等待确认
if (!channel.waitForConfirms()) {System.out.println("消息发送失败");
}
总结
✅ 手动 ACK 机制(避免自动 ACK,确保消息处理完毕后才确认)
✅ 业务去重(数据库唯一索引,Redis SETNX)
✅ TTL + 死信队列(防止重复消费导致的死循环)
✅ 限制并发数(basicQos(1) 限制每个消费者最多消费 1 条)
✅ 发布确认(waitForConfirms() 确保消息可靠投递)
使用这些优化方法,可以有效防止 RabbitMQ 在 高并发情况下的重复消费,保障消息一致性和系统稳定性!🚀
7消息堆积如何处理?
在 RabbitMQ 高并发环境下,如果消息处理速度赶不上生产速度,容易导致 消息堆积,最终可能引发 队列溢出、服务器崩溃 等问题。这里介绍 消息堆积的原因分析 以及 有效的解决方案。
✅ 解决方案
- 增加消费者并发数
方法:
增加 消费者实例(多个 Worker 并发消费)
调整 预取数 prefetch_count,避免一个消费者一次性接收过多消息
📌 示例(Java 代码:增加并发消费者)
channel.basicQos(10); // 每个消费者最多处理 10 条消息
这样可以让消费者更快地处理消息,减少队列堆积。
- 使用消息分片 & 负载均衡
当单个队列压力过大时,可以通过 多队列 + 负载均衡 分担流量:
方法 1:按 消息特性 分片(如订单队列、支付队列、库存队列)
方法 2:多个消费者监听 不同的队列 处理同一类任务
方法 3:使用 交换机(Exchange) 进行路由
📌 示例(不同消费者监听不同的队列)
channel.queueDeclare("order_queue", true, false, false, null);
channel.queueDeclare("payment_queue", true, false, false, null);
优点:避免某一个队列因负载过大而导致 RabbitMQ 挂掉。
- 启用 RabbitMQ 集群
如果 RabbitMQ 单节点性能不足,可以使用 RabbitMQ 集群,提高系统的吞吐能力:
镜像队列模式:保证高可用
分布式队列模式:多个 RabbitMQ 节点共同处理消息
📌 示例(启用集群)
rabbitmqctl join_cluster rabbit@node2
优点:多个 RabbitMQ 服务器 分担流量,避免单点压力过大。
- 配置消息 TTL + 死信队列
如果消息长时间堆积,可以设置 消息过期时间(TTL),并把未处理的消息转入 死信队列(DLX)。
📌 示例(配置 TTL + DLX)
Map<String, Object> args = new HashMap<>();
args.put("x-message-ttl", 60000); // 消息存活 60s
args.put("x-dead-letter-exchange", "dlx_exchange"); // 过期消息转入死信队列
channel.queueDeclare("task_queue", true, false, false, args);
优点:
- 限制消息存活时间,防止无用消息无限堆积。
- 过期消息进入 死信队列,避免影响正常业务。
- 限流(限流+降级)
如果生产者产生消息过快,可以限制生产速度,或直接丢弃部分非核心消息。
限流方式:
- RabbitMQ basic.qos 控制流速
- Kafka 或 Redis 作为缓冲层
- 应用层限流(如令牌桶、漏桶算法)
📌 示例(使用 basic.qos 进行流量控制)
channel.basicQos(5); // 限制每个消费者每次最多消费 5 条
优点:可以防止 RabbitMQ 被瞬时高并发流量压垮。
- 监控 & 自动扩展
- 使用 RabbitMQ 监控工具(Prometheus + Grafana / RabbitMQ Management)
- 设置自动扩容机制(Kubernetes HPA)
📌 示例(监控 RabbitMQ 队列长度)
rabbitmqctl list_queues name messages_ready messages_unacknowledged
如果队列长度超过阈值,可以 动态增加消费者,提高处理能力。
🔥 总结
如果你的 RabbitMQ 消息已经堆积过多,可以:
- 临时增加消费者实例(短期缓解)
- 快速清理过期/无用消息(避免资源占满)
- 优化消息分片 & 负载均衡(长期解决)
8.用过那些监控ivm的工具?
IVM(Intelligent Virtual Machine,智能虚拟机)监控 需要关注 CPU、内存、磁盘、网络 以及 应用服务 的健康状态。常见的 IVM 监控工具有:
✅ 如何实现 IVM 监控
- 使用 Prometheus + Grafana 监控 IVM
架构:
- Node Exporter(采集虚拟机 CPU、内存、磁盘、网络)
- Prometheus(存储 & 报警)
- Grafana(可视化)
📌 步骤 1️⃣ 安装 Node Exporter(虚拟机监控)
wget https://github.com/prometheus/node_exporter/releases/latest/download/node_exporter-linux-amd64.tar.gz
tar -xzf node_exporter-linux-amd64.tar.gz
cd node_exporter-*
./node_exporter &
2️⃣ 配置 Prometheus 采集虚拟机数据 编辑 prometheus.yml:
yaml
scrape_configs:- job_name: 'ivm-monitor'static_configs:- targets: ['192.168.1.100:9100'] # 监控 IVM 的 IP
3️⃣ 运行 Prometheus
./prometheus --config.file=prometheus.yml
4️⃣ 配置 Grafana 可视化
- 在 Grafana 添加数据源(Prometheus)
- 使用 Node Exporter 监控仪表盘展示 CPU、内存、磁盘使用率
- 使用 Zabbix 监控 IVM
1️⃣ 安装 Zabbix Agent 到 IVM
sudo apt install zabbix-agent
sudo systemctl start zabbix-agent
sudo systemctl enable zabbix-agent
2️⃣ 配置 Zabbix Server 在 /etc/zabbix/zabbix_agentd.conf 添加:
Server=192.168.1.200 # Zabbix 服务器 IP
3️⃣ 在 Zabbix Web UI 中添加 IVM 主机
- 配置 CPU、内存、网络监控
- 设置告警阈值(如 CPU 使用率 > 80% 发送告警)
- 使用 ELK 监控 IVM 日志
1️⃣ 安装 Filebeat 采集日志
sudo apt install filebeat
2️⃣ 配置 Filebeat 发送到 Elasticsearch
output.elasticsearch:hosts: ["192.168.1.200:9200"]
3️⃣ 使用 Kibana 可视化 IVM 日志
🚀 总结
- 大规模 IVM 监控 👉 Prometheus + Grafana
- 企业级稳定监控 👉 Zabbix / Nagios
- 日志监控 👉 ELK
- SaaS 监控 👉 Datadog / New Relic
如果是 高并发分布式 IVM 监控,推荐 Prometheus + Grafana,结合 告警 & 自动扩展,确保系统稳定!💡
9.常用的设计模式有哪些?怎么用的?
设计模式(Design Patterns) 是软件开发中的常见问题解决方案,主要分为 三大类:
- 创建型模式(解决对象创建问题)
- 结构型模式(解决类和对象的组合问题)
- 行为型模式(解决对象交互问题)
🔹 1. 创建型模式
✅ 1.1 单例模式(Singleton)
作用:确保一个类只有一个实例,并提供全局访问点
应用场景:数据库连接池、线程池、日志系统
📌 示例(懒汉式,线程安全)
public class Singleton {private static volatile Singleton instance; // 防止指令重排private Singleton() {} // 私有构造函数,防止外部实例化public static Singleton getInstance() {if (instance == null) {synchronized (Singleton.class) {if (instance == null) {instance = new Singleton();}}}return instance;}
}
✅ 1.2 工厂模式(Factory Pattern)
作用:提供一个创建对象的接口,而不是直接实例化类
应用场景:数据库连接、日志记录器
📌 示例
// 1. 定义接口
interface Product {void create();
}// 2. 具体产品实现
class ConcreteProductA implements Product {public void create() { System.out.println("创建产品 A"); }
}class ConcreteProductB implements Product {public void create() { System.out.println("创建产品 B"); }
}// 3. 工厂类
class Factory {public static Product getProduct(String type) {if ("A".equals(type)) return new ConcreteProductA();else if ("B".equals(type)) return new ConcreteProductB();return null;}
}// 4. 使用工厂
Product product = Factory.getProduct("A");
product.create();
🔹 2. 结构型模式
✅ 2.1 适配器模式(Adapter Pattern)
作用:把一个接口转换成客户端期望的另一个接口
应用场景:兼容老代码、新旧接口对接
📌 示例
// 1. 目标接口
interface Target {void request();
}// 2. 被适配者(旧接口)
class Adaptee {void specificRequest() { System.out.println("调用旧接口"); }
}// 3. 适配器
class Adapter implements Target {private Adaptee adaptee = new Adaptee();public void request() { adaptee.specificRequest(); }
}// 4. 使用适配器
Target adapter = new Adapter();
adapter.request();
✅ 2.2 装饰器模式(Decorator Pattern)
作用:动态扩展类的功能,而不修改原代码
应用场景:日志增强、数据加密、I/O 流
📌 示例
// 1. 定义接口
interface Component {void operation();
}// 2. 具体组件
class ConcreteComponent implements Component {public void operation() { System.out.println("基础功能"); }
}// 3. 装饰器基类
class Decorator implements Component {protected Component component;public Decorator(Component component) { this.component = component; }public void operation() { component.operation(); }
}// 4. 具体装饰器
class ConcreteDecorator extends Decorator {public ConcreteDecorator(Component component) { super(component); }public void operation() {super.operation();System.out.println("扩展功能");}
}// 5. 使用装饰器
Component decorated = new ConcreteDecorator(new ConcreteComponent());
decorated.operation();
🔹 3. 行为型模式
✅ 3.1 观察者模式(Observer Pattern)
作用:一对多依赖,当一个对象状态改变,所有依赖对象自动更新
应用场景:事件监听、消息推送
📌 示例
import java.util.ArrayList;
import java.util.List;// 1. 观察者接口
interface Observer {void update(String message);
}// 2. 具体观察者
class User implements Observer {private String name;public User(String name) { this.name = name; }public void update(String message) {System.out.println(name + " 收到消息: " + message);}
}// 3. 主题(被观察者)
class Subject {private List<Observer> observers = new ArrayList<>();public void addObserver(Observer observer) { observers.add(observer); }public void notifyObservers(String message) {for (Observer observer : observers) observer.update(message);}
}// 4. 测试
Subject subject = new Subject();
Observer user1 = new User("张三");
Observer user2 = new User("李四");
subject.addObserver(user1);
subject.addObserver(user2);
subject.notifyObservers("系统升级");
✅ 3.2 策略模式(Strategy Pattern)
作用:定义一系列算法,让它们可以互换,避免 if-else 代码膨胀
应用场景:支付方式、数据压缩、权限验证
📌 示例
// 1. 策略接口
interface Strategy {void execute();
}// 2. 具体策略
class ConcreteStrategyA implements Strategy {public void execute() { System.out.println("执行策略 A"); }
}class ConcreteStrategyB implements Strategy {public void execute() { System.out.println("执行策略 B"); }
}// 3. 上下文(使用策略)
class Context {private Strategy strategy;public void setStrategy(Strategy strategy) { this.strategy = strategy; }public void executeStrategy() { strategy.execute(); }
}// 4. 测试
Context context = new Context();
context.setStrategy(new ConcreteStrategyA());
context.executeStrategy();
context.setStrategy(new ConcreteStrategyB());
context.executeStrategy();
🔥 总结
10.xxl-job如果任务处理不完怎么办?
🔍 任务堆积的原因分析
- 任务执行时间过长(业务逻辑耗时过多、数据库查询慢)
- 任务并发数太少(单个执行器线程数限制)
- 任务调度间隔过短(调度频率高,任务还未执行完就来了新的)
- 任务失败未重试(导致部分任务一直未完成)
- 执行器负载过高(CPU、内存资源耗尽)
✅ 解决方案
- 增加任务并发数
如果执行器并发数太少,任务处理能力有限,可以通过 线程池 提高并发。
📌 方法 1:配置 XXL-Job 线程池
修改 XXL-Job 执行器配置,提高 xxl.job.executor.logretentiondays
xxl.job.executor.logretentiondays=30
xxl.job.executor.threadpool=20
Java 代码示例(使用线程池)
@XxlJob("parallelJobHandler")
public void parallelJobHandler() throws Exception {ExecutorService executorService = Executors.newFixedThreadPool(10); // 增加线程池for (int i = 0; i < 10; i++) {executorService.submit(() -> {System.out.println("处理任务:" + Thread.currentThread().getName());});}executorService.shutdown();
}
- 增加执行器机器
如果任务量特别大,单个 Executor(执行器) 处理不过来,可以 水平扩展,增加多台机器。
📌 方法:配置 XXL-Job 多个执行器
- 在 Nginx 或负载均衡 中配置多个 XXL-Job 执行器
- 在 xxl-job-admin 配置多个 Executor
- 动态扩容:可以使用 Kubernetes(K8s)+ HPA 自动扩展实例
📌 示例(多个执行器注册)
xxl.job.executor.address=http://192.168.1.100:9999,http://192.168.1.101:9999
- 任务分片(Sharding)
如果任务处理不完,可以 拆分任务,让多个执行器同时处理不同数据片段。
📌 方法:使用 XXL-Job 自带的 Sharding
@XxlJob("shardingJobHandler")
public void shardingJobHandler() throws Exception {int shardIndex = XxlJobHelper.getShardIndex(); // 当前执行器分片索引int shardTotal = XxlJobHelper.getShardTotal(); // 总分片数System.out.println("执行分片:" + shardIndex + "/" + shardTotal);
}
作用:如果有 10000 条数据,可以分 10 片,每个执行器处理 1000 条,提升任务吞吐量。
- 任务超时 & 限流
如果任务执行时间过长,导致后续任务堆积,可以:
设置任务超时时间
限制最大并发数
📌 方法:配置 XXL-Job 超时 & 并发
@XxlJob(value = "timeoutJobHandler", init = "initMethod", destroy = "destroyMethod", timeout = 5000, concurrent = false)
public void timeoutJobHandler() throws Exception {Thread.sleep(6000); // 模拟超时
}
timeout = 5000:超时 5 秒后强制结束任务
concurrent = false:不允许并发执行,防止任务堆积
- 失败重试
如果任务失败,可能会导致数据未处理完。可以开启 失败重试,让 XXL-Job 自动尝试执行。
📌 方法:在 XXL-Job 控制台配置
- 重试次数:默认 3 次
- 失败策略:
-
- 失败重试(RETRY)
-
- 失败报警(FAIL_ALARM)
-
- 丢弃后续任务(DISCARD_LATER)
- 任务排队(消息队列)
如果任务量超大,可以引入 消息队列(MQ) 进行流量削峰。
📌 方法:使用 RabbitMQ / Kafka 进行异步处理
@XxlJob("mqJobHandler")
public void mqJobHandler() throws Exception {String message = "任务数据";rabbitTemplate.convertAndSend("taskQueue", message);
}
让 XXL-Job 只负责写入 MQ,执行器异步消费,防止任务堆积。
🔥 总结
📌 综合优化:
✅ 短期优化 👉 线程池、任务分片、超时处理
✅ 长期优化 👉 负载均衡、多执行器、异步消息队列
如果 XXL-Job 任务一直堆积,建议结合 任务分片 + 多执行器 + MQ 方案,确保高并发场景下任务稳定运行!🚀
11.spring事务失效情况,传播机制,如何保证事务不失效
🔹 1. Spring 事务失效的常见原因
在 Spring 中,事务由 @Transactional 注解管理,但在某些情况下事务可能会失效。常见失效情况包括:
🔹 2. 事务传播机制(Transaction Propagation)
Spring 事务提供 7 种事务传播机制,主要用于嵌套调用时事务的行为控制:
📌 示例
@Service
public class OrderService {@Transactional(propagation = Propagation.REQUIRED)public void createOrder() {userService.addUser(); // 事务加入当前事务paymentService.processPayment(); // 事务加入当前事务}
}
🔹 3. 如何保证事务不失效
为了确保事务能够正常生效,推荐采取以下措施:
✅ 1. @Transactional 方法必须是 public
📌 错误示例(私有方法无效)
@Service
public class MyService {@Transactionalprivate void saveData() { // ❌ 无效// 事务不会生效}
}
📌 正确示例
@Service
public class MyService {@Transactionalpublic void saveData() { // ✅ 必须是 public// 事务正常生效}
}
✅ 2. 确保 @Transactional 方法是由 Spring 托管的 Bean 调用
📌 错误示例(内部调用失效)
@Service
public class MyService {@Transactionalpublic void methodA() {methodB(); // ❌ 内部调用,事务失效}@Transactionalpublic void methodB() {// 事务不会生效}
}
📌 正确示例
@Service
public class MyService {@Transactionalpublic void methodA() {((MyService) AopContext.currentProxy()).methodB(); // ✅ 通过代理调用}@Transactionalpublic void methodB() {// 事务正常生效}
}
✅ 3. 事务异常必须是 RuntimeException
📌 错误示例(捕获异常后事务不回滚)
java
复制
编辑
@Transactional
public void updateData() {
try {
// 业务逻辑
} catch (Exception e) { // ❌ 事务不会回滚
e.printStackTrace();
}
}
📌 正确示例
java
复制
编辑
@Transactional
public void updateData() {
try {
// 业务逻辑
} catch (Exception e) {
TransactionAspectSupport.currentTransactionStatus().setRollbackOnly(); // ✅ 手动回滚
}
}
✅ 4. 多线程事务控制
📌 错误示例(子线程不继承事务)
@Transactional
public void process() {new Thread(() -> saveData()).start(); // ❌ 事务不会生效
}
📌 正确示例
@Transactional
public void process() {CompletableFuture.runAsync(() -> saveData(), Executors.newFixedThreadPool(5)); // ✅ 线程池事务
}
✅ 5. 事务嵌套 & Propagation.REQUIRES_NEW
如果主事务和子事务相互独立,可以使用 REQUIRES_NEW。
📌 示例
@Service
public class OrderService {@Transactional(propagation = Propagation.REQUIRED)public void createOrder() {paymentService.processPayment(); // 事务 A}
}@Service
public class PaymentService {@Transactional(propagation = Propagation.REQUIRES_NEW)public void processPayment() {// 事务 B,独立提交,不受主事务影响}
}
🔥 总结
📌 最佳实践:
- 所有 @Transactional 方法必须是 public
- 确保方法是由 Spring 管理的 Bean 调用(避免内部调用)
- 抛出的异常必须是 RuntimeException,或手动 setRollbackOnly()
- 多线程时要手动绑定事务
- 事务传播机制要合理选择(REQUIRES_NEW / NESTED 等)
12.dubbo和openfeiqn的区别?
13.nacos支持负载均衡吗,策略是什么?
14.了解过逃逸分析吗?
15.hashmap底层结构,什么时间会形成链表,idk1.8前后有啥区别
16.jvm内存结构,新生代的垃圾回收算法,老年代的垃圾回收算法
17.如何创建线程,start方法可不可以调两次,一个线程如何唤起另一个线程。
18.syncornized和Lock有什么区别
19.volatile关键字的实现原理
20.线程池的基本原理,具体参数是什么
21.redis线程模型,redis的主从、哨兵、集群模式区别
22.消息堆积如何处理,消息重复消费如何避免
23.使用过的设计模式
24.mysql的索引原理
25.sql优化方法
26.springcloud用过哪些组件
相关文章:
java面试场景问题
还在补充,这几天工作忙,闲了会把答案附上去,也欢迎各位大佬评论区讨论 1.不用分布式锁如何防重复提交 方法 1:基于唯一请求 ID(幂等 Token) 思路:前端生成 一个唯一的 requestId(…...
MySQL数据库基本概念
目录 什么是数据库 从软件角度出发 从网络角度出发 MySQL数据库的client端和sever端进程 mysql的client端进程连接sever端进程 mysql配置文件 MySql存储引擎 MySQL的sql语句的分类 数据库 库的操作 创建数据库 不同校验规则对查询的数据的影响 不区分大小写 区…...
【wiki知识库】07.用户管理后端SpringBoot部分
目录 一、今日目标 二、??SpringBoot部分类的添加 2.1 使用逆向工程新增User模块 2.2 UserQueryParam添加 2.3 UserSaveParam添加 2.4 UserResetPasswordParam添加 2.5 UserQueryVo添加 2.6 SnowFlake工具类 三、??后端新增接口? 3.1 /user/list接口添加 3.2 /…...
千峰React:案例二
完成对html文档还有css的引入,引入一下数据: import { func } from prop-types import ./购物车样式.css import axios from axios import { useImmer } from use-immer import { useEffect } from reactfunction Item() {return (<li classNameacti…...
Junit框架缺点
JUnit 是 Java 生态中最流行的单元测试框架,广泛应用于单元测试和集成测试中。尽管它功能强大且易于使用,但也存在一些缺陷和局限性。以下是 JUnit 的主要缺点: 1. 功能相对固定 问题:JUnit 的核心功能相对固定,缺乏灵…...
计算机毕业设计SpringBoot+Vue.js公司日常考勤系统(源码+文档+PPT+讲解)
温馨提示:文末有 CSDN 平台官方提供的学长联系方式的名片! 温馨提示:文末有 CSDN 平台官方提供的学长联系方式的名片! 温馨提示:文末有 CSDN 平台官方提供的学长联系方式的名片! 作者简介:Java领…...
Python线程池知多少
目录 目标 Python版本 官方文档 概述 线程池 实战 创建线程池的基本语法 批量提交任务 生产者&消费者模型 目标 掌握线程池的基本概念和使用方法。 Python版本 Python 3.9.18 官方文档 concurrent.futures — Launching parallel taskshttps://docs.python.org/3…...
MySQL数据库入门到大蛇尚硅谷宋红康老师笔记 高级篇 part 6
从6到12章将会是重中之重,请一定好好看 第06章_索引的数据结构 1.为什么使用索引 索引是存储引擎用于快速找到数据记录的一种数据结构,就好比一本教课书的目录部分,通过目录中找到对应文章的页码,便可快速定位到需要的文章。MySQL中也是一…...
C++动态与静态转换区别详解
文章目录 前言一、 类型检查的时机二、安全性三、适用场景四、代码示例对比总结 前言 在 C 中,dynamic_cast 和 static_cast 是两种不同的类型转换操作符,主要区别体现在类型检查的时机、安全性和适用场景上。以下是它们的核心区别: 一、 类…...
面向AI 的前端发展及初识大模型
AI带来的开发范式迁移 随着AI的涌现,对前端的发展也有着非常大的影响,总结过去前端的发展路径,目前应该属于又一次的大规模的开发范式迁移阶段。上一个阶段是从jquery到React/Vue/Angular迁移(jquery之前的就不讨论了)…...
Java入门的基础学习
Java的基础语法知识 一 初始Java二 Java数据类型和变量1.字面常量2.数据类型基本数据类型引用数据类型 3.变量整型变量浮点型变量字符型变量布尔型变量 4.类型转化和提升类型转化类型提升 三 运算符1.算数运算符2.关系操作符3.逻辑运算符:&&,||&…...
万字详解 MySQL MGR 高可用集群搭建
文章目录 1、MGR 前置介绍 1.1、什么是 MGR1.2、MGR 优点1.3、MGR 缺点1.4、MGR 适用场景 2、MySQL MGR 搭建流程 2.1、环境准备2.2、搭建流程 2.2.1、配置系统环境2.2.2、安装 MySQL2.2.3、配置启动 MySQL2.2.4、修改密码、设置主从同步2.2.5、安装 MGR 插件 3、MySQL MGR 故…...
脚本无法获取响应主体(原因:CORS Missing Allow Credentials)
背景: 前端的端口号8080,后端8000。需在前端向后端传一个参数,让后端访问数据库去检测此参数是否出现过。涉及跨域请求,一直有这个bug是404文件找不到。 在修改过程当中不小心删除了一段代码,出现了这个bug࿰…...
GD32F450 使用
GB32F450使用 1. 相关知识2. 烧写程序3. SPI3.1 spi基础3.2 spi代码 4. 串口4.1 串口引脚4.2 串口通信代码 问题记录1. 修改晶振频率 注意:GD32F450 总共有三种封装形式,本文所述的相关代码和知识,均为 GD32F450IX 系列。 1. 相关知识 参数配…...
神经网络代码入门解析
神经网络代码入门解析 import torch import matplotlib.pyplot as pltimport randomdef create_data(w, b, data_num): # 数据生成x torch.normal(0, 1, (data_num, len(w)))y torch.matmul(x, w) b # 矩阵相乘再加bnoise torch.normal(0, 0.01, y.shape) # 为y添加噪声…...
Android 数据库查询对比(APN案例)
功能背景 APN 数据通常存储在数据库中,由TelephonyProvider提供。当用户进入APN设置界面时,Activity会启动,AOSP源码通过ContentResolver查询APN数据。关键分析点在于这个查询操作是否在主线程执行,因为主线程上的耗时操作会导致…...
神卓 S500 异地组网设备实现监控视频异地组网的详细步骤
一、设备与环境准备 硬件清单 主设备:神卓 S500 异地组网路由器 1子设备:神卓 S500 或兼容设备 N(需通过官网认证)监控设备:支持 RTSP/ONVIF 协议的 NVR、摄像头网络要求:各网点需稳定联网(推荐…...
golang安装(1.23.6)
1.切换到安装目录 cd /usr/local 2.下载安装包 wget https://go.dev/dl/go1.23.6.linux-amd64.tar.gz 3.解压安装包 sudo tar -C /usr/local -xzf go1.23.6.linux-amd64.tar.gz 4.配置环境变量 vi /etc/profile export PATH$…...
leetcode35.搜索插入位置
题目: 给定一个排序数组和一个目标值,在数组中找到目标值,并返回其索引。如果目标值不存在于数组中,返回它将会被按顺序插入的位置。 请必须使用时间复杂度为 O(log n) 的算法。 示例 1: 输入: nums [1,3,5,6], target 5 输出…...
LeetCode第57题_插入区间
LeetCode 第57题:插入区间 题目描述 给你一个 无重叠的 ,按照区间起始端点排序的区间列表。在列表中插入一个新的区间,你需要确保列表中的区间仍然有序且不重叠(如果有必要的话,可以合并区间)。 难度 中…...
人工智能之数学基础:线性代数中矩阵的运算
本文重点 矩阵的运算在解决线性方程组、描述线性变换等方面发挥着至关重要的作用。通过对矩阵进行各种运算,可以简化问题、揭示问题的本质特征。在实际应用中,我们可以利用矩阵运算来处理图像变换、数据分析、电路网络等问题。深入理解和掌握矩阵的运算,对于学习线性代数以…...
SQL Server 创建用户并授权
创建用户前需要有一个数据库,创建数据库命令如下: CREATE DATABASE [数据库名称]; CREATE DATABASE database1;一、创建登录用户 方式1:SQL命令 命令格式:CREATE LOGIN [用户名] WITH PASSWORD ‘密码’; 例如,创…...
MySQL双主搭建-5.7.35
文章目录 上传并安装MySQL 5.7.35双主复制的配置实例一:172.25.0.19:实例二:172.25.0.20: 配置复制用户在实例 1 (172.25.0.19)上执行:在实例 2 (172.25.0.20)上执行&…...
RNN实现精神分裂症患者诊断(pytorch)
RNN理论知识 RNN(Recurrent Neural Network,循环神经网络) 是一种 专门用于处理序列数据(如时间序列、文本、语音、视频等)的神经网络。与普通的前馈神经网络(如 MLP、CNN)不同,RNN…...
Python中字符串的常用操作
一、r原样输出 在 Python 中,字符串前加 r(即 r"string" 或 rstring)表示创建一个原始字符串(raw string)。下面详细介绍原始字符串的特点、使用场景及与普通字符串的对比。 特点 忽略转义字符࿱…...
uniapp 本地数据库多端适配实例(根据运行环境自动选择适配器)
项目有个需求,需要生成app和小程序,app支持离线数据库,如果当前没有网络提醒用户开启离线模式,所以就随便搞了下,具体的思路就是: 一个接口和多个实现类(类似后端的模板设计模式)&am…...
Spring Cloud Gateway 整合Spring Security
做了一个Spring Cloud项目,网关采用 Spring Cloud Gateway,想要用 Spring Security 进行权限校验,由于 Spring Cloud Gateway 采用 webflux ,所以平时用的 mvc 配置是无效的,本文实现了 webflu 下的登陆校验。 1. Sec…...
【异地访问本地DeepSeek】Flask+内网穿透,轻松实现本地DeepSeek的远程访问
写在前面:本博客仅作记录学习之用,部分图片来自网络,如需引用请注明出处,同时如有侵犯您的权益,请联系删除! 文章目录 前言依赖Flask构建本地网页访问LM Studio 开启网址访问DeepSeek 调用模板Flask 访问本…...
Windows对比MacOS
Windows对比MacOS 文章目录 Windows对比MacOS1-环境变量1-Windows添加环境变量示例步骤 1:打开环境变量设置窗口步骤 2:添加系统环境变量 2-Mac 系统添加环境变量示例步骤 1:打开终端步骤 2:编辑环境变量配置文件步骤 3࿱…...
React实现无缝滚动轮播图
实现效果: 由于是演示代码,我是直接写在了App.tsx里面在 文件位置如下: App.tsx代码如下: import { useState, useEffect, useCallback, useRef } from "react"; import { ImageContainer } from "./view/ImageC…...
Ubuntu20.04确认cuda和cudnn已经安装成功
当我们通过官网安装cuda和cudnn时,终端执行完命令后我们仍不能确定是否已经安装成功。接下来教大家用几句命令测试。 cuda 检测版本号 nvcc -V如果输出如下,则安装成功。 可以看到版本号是11.2 cudnn检测版本号 有两种命令:如果你的cudn…...
sqlilab 46 关(布尔、时间盲注)
sqlilabs 46关(布尔、时间盲注) 46关有变化了,需要我们输入sort,那我们就从sort1开始 递增测试: 发现测试到sort4就出现报错: 我们查看源码: 从图中可看出:用户输入的sort值被用于查…...
AI时代保护自己的隐私
人工智能最重要的就是数据,让我们面对现实,大多数人都不知道他们每天要向人工智能提供多少数据。你输入的每条聊天记录,你发出的每条语音命令,人工智能生成的每张图片、电子邮件和文本。我建设了一个网站(haptool.com),…...
模型优化之强化学习(RL)与监督微调(SFT)的区别和联系
强化学习(RL)与监督微调(SFT)是机器学习中两种重要的模型优化方法,它们在目标、数据依赖、应用场景及实现方式上既有联系又有区别。 想了解有关deepseek本地训练的内容可以看我的文章: 本地基于GGUF部署的…...
Buildroot 添加自定义模块-内置文件到文件系统
目录 概述实现步骤1. 创建包目录和文件结构2. 配置 Config.in3. 定义 cp_bin_files.mk4. 添加源文件install.shmy.conf 5. 配置与编译 概述 Buildroot 是一个高度可定制和模块化的嵌入式 Linux 构建系统,适用于从简单到复杂的各种嵌入式项目. buildroot的源码中bui…...
蓝牙接近开关模块感应开锁手机靠近解锁支持HID低功耗
ANS-BT101M是安朔科技推出的蓝牙接近开关模块,低功耗ble5.1,采用UART通信接口,实现手机自动无感连接,无需APP,人靠近车门自动开锁,支持苹果、安卓、鸿蒙系统,也可以通过手机手动开锁或上锁&…...
计算机毕业设计SpringBoot+Vue.js基于工程教育认证的计算机课程管理平台(源码+文档+PPT+讲解)
温馨提示:文末有 CSDN 平台官方提供的学长联系方式的名片! 温馨提示:文末有 CSDN 平台官方提供的学长联系方式的名片! 温馨提示:文末有 CSDN 平台官方提供的学长联系方式的名片! 作者简介:Java领…...
企业知识库搭建:14款开源与免费系统选择
本文介绍了以下14 款知识库管理系统:1.Worktile;2.PingCode;3.石墨文档; 4. 语雀; 5. 有道云笔记; 6. Bitrix24; 7. Logseq等。 在如今的数字化时代,企业和团队面临着越来越多的信息…...
蓝桥杯(握手问题)
小蓝组织了一场算法交流会议,总共有 50 人参加了本次会议。在会议上,大家进行了握手交流。按照惯例他们每个人都要与除自己以外的其他所有人进行一次握手 (且仅有一次)。 但有 7个人,这 7 人彼此之间没有进行握手 (但这 7 人与除这 7 人以外…...
如何使用 Jenkins 实现 CI/CD 流水线:从零开始搭建自动化部署流程
如何使用 Jenkins 实现 CI/CD 流水线:从零开始搭建自动化部署流程 在软件开发过程中,持续集成(CI)和持续交付(CD)已经成为现代开发和运维的标准实践。随着代码的迭代越来越频繁,传统的手动部署方式不仅低效,而且容易出错。为了提高开发效率和代码质量,Jenkins作为一款…...
c++字符编码/乱码问题
基本概念 c11版本引入了char16_t和char32_t两个类型,他们的特点分别如下: char16_t 16位的unicode字符类型用于表示UTF-16编码大小:2字节字面量前缀:u char32_t 32位unicode字符类型用于表示UTF-32编码大小:4字节…...
侯捷 C++ 课程学习笔记:深入理解类与继承
文章目录 每日一句正能量一、课程背景二、学习内容:类与继承(一)类的基本概念1. 类的定义与实例化2. 构造函数与析构函数 (二)继承1. 单继承与多继承2. 虚函数与多态 三、学习心得四、总结 每日一句正能量 有种承担&am…...
初始化列表
一:声明,定义,赋值的区别 ①:声明 这里,int _year; int _month;int _day; 是成员变量的声明,它们告诉编译器: 类 Date中有三个成员变量_year和 _month和_day。 它们的类型分别都是 int 此…...
7.1 - 定时器之中断控制LED实验
文章目录 1 实验任务2 系统框图3 软件设计 1 实验任务 本实验任务是通过CPU私有定时器的中断,每 200ms 控制一次PS LED灯的亮灭。 2 系统框图 3 软件设计 注意事项: 定时器中断在收到中断后,只需清除中断状态,无需禁用中断、启…...
Pytest之fixture的常见用法
文章目录 1.前言2.使用fixture执行前置操作3.使用conftest共享fixture4.使用yield执行后置操作 1.前言 在pytest中,fixture是一个非常强大和灵活的功能,用于为测试函数提供固定的测试数据、测试环境或执行一些前置和后置操作等, 与setup和te…...
【分库分表】基于mysql+shardingSphere的分库分表技术
目录 1.什么是分库分表 2.分片方法 3.测试数据 4.shardingSphere 4.1.介绍 4.2.sharding jdbc 4.3.sharding proxy 4.4.两者之间的对比 5.留个尾巴 1.什么是分库分表 分库分表是一种场景解决方案,它的出现是为了解决一些场景问题的,哪些场景喃…...
合并两个有序链表:递归与迭代的实现分析
合并两个有序链表:递归与迭代的实现分析 在算法与数据结构的世界里,链表作为一种基本的数据结构,经常被用来解决各种问题。特别是对于有序链表的合并,既是经典面试题,也是提高编程能力的重要练习之一。合并两个有序链…...
HTML AI 编程助手
HTML AI 编程助手 引言 随着人工智能技术的飞速发展,编程领域也迎来了新的变革。HTML,作为网页制作的基础语言,与AI技术的结合,为开发者带来了前所未有的便利。本文将探讨HTML AI编程助手的功能、应用场景以及如何利用它提高编程…...
备战蓝桥杯Day11 DFS
DFS 1.要点 (1)朴素dfs 下面保存现场和恢复现场就是回溯法的思想,用dfs实现,而本质是用递归实现,代码框架: ans; //答案,常用全局变量表示 int mark[N]; //记录状态i是否被处理过 …...
Oracle 认证为有哪几个技术方向
Oracle 认证技术方向,分别是数据库管理、开发、云平台,每个方向都有不同的学习等级 数据库运维方向 Oracle Certified Professional(OCP):19c OCA内容已和OCP合并 OCP 19c属于oracle认证专家,要求考生掌握深…...