6月7号
今天让claude code帮我出了一个项目来帮我串一下学到的内容
1.重写AQS的tryacquire还有tryrelease
tryAcquire
if(getsata()==0&&CAS(0,2))
{
setsatta(1);
setExclusiveOwnerThread(Thread.currentThread());
return true;
}
return false;
tryRelease
setstata(0);
setExclusiveOwnerThread(null);
return true
手写这个的目的只是为了理解基于AQS互斥锁的原理
1.线程尝试拿锁
2.如果拿到将sata设置成1,并且将持锁线程设置成当前线程
3.如果没拿到锁就进入
2.redis解决缓存穿透还有缓存雪崩
缓存穿透:
用cache-aside模式去读库 先读redis如果没有就异步去读数据库同时刷新redis
String key="product:"+id;
Object cache=redisTemplate.opsforvalue.get(key);
if(cache!=null){
cacheHits().incrementAndGet() //缓存击中
return (Product)cache
}
cacheMiss.incrementAndGet();
Product product=queryFromDbWithCacheProtection(id); //互斥锁去数据库拿数据同时更新缓存
if(product!=null){
int ttl=BASE_TTL_MINUTES*60+RANDOM.nextInt(600);
redisTemplate.opsforvalues.set(key, product, Duration.ofSeconds(ttl)) //设置随机ttl避免雪崩
}
return product;
public Product queryFromDbWithCacheProtection(id){ //互斥锁
String lockkey="lock:product:"+id;
String uuid = UUID.randomUUID().toString();
try{
boolean lock=redisTemplate.opsgorValue.setIfAbsent(key,uuid,10,TimeUnit.SECONDS);
if(BOOLEAN.TRUE.euqals(lock)){
try{
ProductEntity product1=productMapper.selectById(id);
return product1!=null?toDto(product1):null;
}
finally{
redisTemplate.delet(lockkey);
}
else{
Thread.sleep(50); //睡50ms避免大量请求同时再去请求数据库
object cache1 = redisTemplate.opsforvalue.get("product:"+id);
return cache1!=null?Product(cache1):null
}
catch(interruptExecption e)
Thread.currentThread.interrput();
return null;
}
}
}
}
3.更新保持缓存和数据库一致性
先更新DB再删缓存
4.mybatis-plus
通过创建Entity实体类与数据库建立联系
获取数据后转化为DTO返回给前端
非常的方便不用手写SQL
动态查询时用wrapper
if(category!=null&&!category.isEmpty())
{
wrappre.eq(ProductEntity::getcategory,category);
}
if(minPrice!=null)
{
wrapper.gt(ProductEntity::getprice,minprice)
}
mybatis-plus还自带分页查询
Page
5.流式转换
Page
productpage.setRecords(productEntitypage.getRecords().stream().map(this::toDto()).toList());
6.线程池
public ThreadpoolExecutor orderAsync(){
return newThreadpoolExecutor(
ASYNC_POOL_CORE_SIZE, //核心线程数
ASYNC_POOL_MAX_SIZE, //最大线程数
ASYNC_POOL_KEEP_ALIVE_SECONDS, //最大存活时间
TimeUnit.SECONDS, //时间单位
new LinkedBlockingQueue<>(ASYNC_POOL_QUEUE_SIZE), //队列最大数
new ThreadFactory() { //线程工厂
private int i = 1;
@Override
public Thread newThread(Runnable r) { //重写newThread方法
return new Thread(r, ASYNC_POOL_NAME + (i++)); r为任务线程,线程名+自加数构成线程名
}
},
new ThreadPoolExecutor.CallerRunsPolicy() //拒绝策略;反压 反压策略会告诉controller前端等说我接收不过来了前端返回友好提示
)
}

浙公网安备 33010602011771号