java场景题30-44
三十、MVCC(多版本并发控制器)
事务隔离级别的无锁实现方式,提高事务的并发性能。
事务隔离级别:解决多个事务并发产生的问题。
读未提交:会产生脏读:事务1修改某个值,事务2读取的是事务1修改的值,但事务1失败执行回滚。
读已提交:产生不可重复读问题;
重复读:解决幻读;
串行化:
MVCC:隐藏列(DB_TRX_ID:当前数据由哪个事务id维护的(持有),DB_ROLL_PTR:当前数据修改前的数据的指针,维护主键id)
三十一、用户忘记密码为什么只能重置密码
系统不知道用户的密码
md5加密(24字符):只能加密不能解密,抗碰撞性不强(哈希冲突,密码可能会一样),同一字符串生成密文一样。(加盐,程序内密码拼接随机字符串)
sha256(64字符):每次生成密文一样,碰撞性增强。
BCrypt(60长度):spring添加依赖即可使用.
三十二、Java实现简单的消息队列
生产者消费者模式,队列,生产者,消费者,锁。
package org.springframework.boot.pradco;
import javax.swing.text.TableView;
import java.util.concurrent.ArrayBlockingQueue;
public class test {
//声明一个数组队列(最大长度)
//消息队列
private int queueSize=10;
private ArrayBlockingQueue<Integer> queue=new ArrayBlockingQueue(queueSize);
public static void main(String[] args) {
//实例化类
test test=new test();
//创建一个消费者,持续监听
Consumer consumer=test.new Consumer();
consumer.start();
//循环生产
for (int i = 0; i < 10; i++) {
Producer producer=test.new Producer();
producer.start();
}
}
//生产者
class Producer extends Thread {
@Override
public void run() {
//保证生产者线程安全
synchronized (queue){
//判断当前队列长度是否小于最大长度
if(queue.size()<queueSize){
//小于就生产消息
//向队列添加一条消息
queue.add(queue.size()+1);
//唤醒消费者
System.out.println("添加了一条消息"+queue.size());
queue.notify();
//模拟业务处理
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
else{
//大于生产者停止工作
try {
queue.wait();
} catch (InterruptedException e1) {
e1.printStackTrace();
//出现异常,手动唤醒
queue.notify();
}
}
}
}
}
//消费者
//写一个消费者(consumer)继承Tread
class Consumer extends Thread{
//重写Run方法
@Override
public void run() {
//死循环持续输出
while(true){
//添加同步锁保证线程安全
synchronized (queue){
//队列为空,线程停止
if(queue.isEmpty()){
System.out.println("当前为空队列");
try {
queue.wait();
} catch (InterruptedException e) {
e.printStackTrace();
//出现异常,手动唤醒
queue.notify();
//模拟业务处理
try {
Thread.sleep(1000);
} catch (InterruptedException e1) {
e1.printStackTrace();
}
}
}else{
//消费头部消息
Integer poll = queue.poll();
System.out.println("消费了一条消息"+poll+" "+queue.size());
//唤醒生产者
queue.notify();
}
}
}
}
}
}
这段代码实现了一个经典的 生产者-消费者模式,通过 ArrayBlockingQueue 和线程同步机制来协调生产和消费行为。
核心结构:
- 消息队列:使用
ArrayBlockingQueue<Integer>作为共享缓冲区,容量为10 - 生产者线程 (
Producer):- 继承
Thread类,每次向队列添加一条消息(值为当前队列大小+1) - 使用
synchronized(queue)保证线程安全 - 队列满时调用
queue.wait()等待 - 生产完成后调用
queue.notify()唤醒消费者
- 继承
- 消费者线程 (
Consumer):- 继承
Thread类,通过while(true)持续监听队列 - 使用
synchronized(queue)保证线程安全 - 队列为空时调用
queue.wait()等待 - 消费完成后调用
queue.notify()唤醒生产者
- 继承
- 主方法流程:
- 创建一个消费者线程并启动(持续监听)
- 循环创建10个生产者线程并启动(每个生产一条消息)
同步机制:通过 wait()/notify() 实现线程间通信,确保生产者不会向满队列写入,消费者不会从空队列读取。
三十三、线上突发bug本地正在开发新需求
git,提交分支当下,复制一个线上版本进行修改,merging到想合并的分支。
1.暂存正在开发的分支(dev)。
2.严重的话先回滚到上一个版本,不严重在(fix)分支修改。
3.十分紧急:直接合并到(master分支),上线
一般:合并到(release)分支,测试,上线
非紧急:合并到dev分支,测试,上线
三十四、RestTemplate如何优化连接池
默认没有连接池,进行远程访问,每次创建一个http链接
HTTP client:配置依赖,修改redistemplate默认的http工厂
三十五、用锁实现线程安全,并将性能提升到极致
使用synchronized锁的对象根据情况认定,比如一个考试系统根据不同的班级分类,锁的是班级号性能就会更高,同一个班级会使用锁串行,不同班级并行。(class.intern()获取到字符串常量,锁这个锁的就是常量而不是字符串)但是常量是共享的会影响加入班级的性能。
三十六、策略模式+简单工厂+模板方法
三十七、springBoot防止反编译
使用 classfinal-maven-plugin 对编译后的 class 文件加密,
运行时通过 -javaagent 加载解密代理,内存中实时解密,
防止反编译拿到源码,保护核心代码(如 AI 密钥、RAG 配置、支付逻辑)。
<build>
<plugins>
<!-- ClassFinal 加密插件 -->
<plugin>
<groupId>net.roseboy</groupId>
<artifactId>classfinal-maven-plugin</artifactId>
<version>1.2.2</version>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>encrypt</goal>
</goals>
</execution>
</executions>
<configuration>
<!-- 加密密码 -->
<password>abc123456</password>
<!-- 要加密的包名 -->
<packages>com.zhou.book,com.zhou.ai</packages>
<!-- 排除启动类不加密(必须) -->
<exclude>com.zhou.BookApplication</exclude>
<!-- 是否开启项目启动后删除 lib 下加密包 -->
<delete>false</delete>
</configuration>
</plugin>
</plugins>
</build>
然后进行打包,运行方法
java -javaagent:xxx-encrypted.jar=abc123456 -jar xxx-encrypted.jar
三十八、spring正常springBoot报错的问题
1.重名bean:spring后面的会覆盖前面的但在sprigBoot中会报错。
spring:
main:
allow-bean-definition-overriding: true
**2.循环依赖:**spring是兼容的但是SpringBoot不兼容。
spring:
main:
allow-circular-references: true
**3.@Value获取不到值:**spring会直接将表达式设置为值,但springboot会报错
spring:
context:
resourceloader:
ignore-unresolvable: true
**4.Aop默认动态代理实现:**spring默认使用jdk,但是SpringBoot默认使用CGLIB
spring:
aop:
proxy-target-class: false
三十九、记录mybatis的sql耗时
四十、SpringBoot敏感信息如何加密
SpringBoot + Jasypt 配置文件加密
1.配置依赖
<!-- Jasypt 加密 Starter -->
<dependency>
<groupId>com.github.ulisesbocchio</groupId>
<artifactId>jasypt-spring-boot-starter</artifactId>
<version>3.0.5</version>
</dependency>
2.生成密文
import org.jasypt.encryption.pbe.StandardPBEStringEncryptor;
public class JasyptUtil {
public static void main(String[] args) {
StandardPBEStringEncryptor encryptor = new StandardPBEStringEncryptor();
// 加密密钥(自己定义,启动时传入)
encryptor.setPassword("zhou_2025_abc");
// 要加密的原文:数据库密码、Redis密码、AI密钥等
String encrypt = encryptor.encrypt("root123456");
System.out.println("加密后:" + encrypt);
}
}
或
java -cp jasypt-1.9.3.jar org.jasypt.intf.cli.JasyptPBEStringEncryptionCLI input="root123456" password="zhou_2025_abc" algorithm=PBEWithMD5AndDES
3.yml配置
spring:
# 数据库加密配置
datasource:
username: root
# 密码用 ENC() 包裹
password: ENC(QeKzJZ9x8xJz9xJz9xJz9xJz9xJz9xJz9)
url: jdbc:mysql://localhost:3306/book_store?useSSL=false
# Redis 密码也可以加密
redis:
host: localhost
port: 6379
password: ENC(xxxxxxx)
# Jasypt 核心配置(指定加密算法)
jasypt:
encryptor:
algorithm: PBEWithMD5AndDES
4.启动
命令方法
java -jar xxx.jar --jasypt.encryptor.password=zhou_2025_abc
IDEA启动(Run/Debug Configurations → VM options)
-Djasypt.encryptor.password=zhou_2025_abc
四十一、微服务feign第一次调用为什么这么慢
第一次要初始化负载均衡(load balance),从nacos拉取服务,http的三次握手四次挥手。
前两个启动时即加载
loadbalancer.eager-load.enabled=true
关闭懒加载,启动时就初始化负载均衡器
第三个可以添加连接池。
四十二、jvm锁机制揭秘
MarkWord都存储了什么标记位,为什么升级为偏向锁后对象头会发生变化,如果对象正处于偏向锁被其他线程抢了会怎么样。
new一个对象堆中就会记录这个对象的信息,其中有一个MarkWord的区域。
MarkWord:8个字节64个bit位组成; 会根据所的状态记录不同的内容。
当我们创建一个对象会有未使用区域(25bit),hashcode区域(31bit),用于垃圾回收的分代年龄,后三位记录锁的信息(无锁状态为001)。如果使用synchronizd锁住后就会升级为偏向锁,前54位保存持有当前锁的线程ID,后三位变成101,jdk15后撤销掉偏向锁,升级为轻量级锁,并行获取升级为重量级锁。
总结:默认无锁状态,单线程同步锁升级为轻量级锁,多线程交替执行,串行就会升级位轻量级锁(CAS判断是否被其他线程持有),多线程并行竞争升级为重量级锁(操作系统的monitor组件实现互斥,用户态》》内核态)。
四十三、直播间多人同时点赞
极高写入,海量读取,极致实时,成本平衡
前端:1s内将点赞数聚合,只发一次请求
业务层:单个用户点赞数量限制
网关层:再次聚合
后端:使用MQ流量削峰。(redis使用incr增加)
消费端统计:redis增加后数据同步到本地缓存,redis中的数据异步同步到数据库。
智能推送:定时进行随机取样少量推送。
四十四、线上redis怎么部署
1.单实例模式:简单,服务器宕机不可用,内存大小有限,有数据丢失风险。
2.主从+哨兵:读写分离(一主用来写入,两从用来读取),数据备份,海量数据存储存在瓶颈。
哨兵:定期向主节点发送消息检测,如果主节点无响应,将从节点选择一个作为主节点。
3.分片集群+一致性Hash:
更多推荐

所有评论(0)