news 2026/11/3 18:19:29

2026-10-13学习总结

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
2026-10-13学习总结

总结:3道算法+八股面经+docker安装和实验报告

括号生成
给一个n代表括号的对数,设计一个函数,用于能够生成所有可能的并且有效的括号组合。

有效:

  1. 全局:左括号总数 = 右括号总数 = n;
  2. 任意前缀:已出现的左括号数 ≥ 右括号数(否则会出现())这种「右括号没人配」的死局)。

思路:使用 回溯 + 剪枝
递归过程中只维护三个量:

变量含义决策
open已经用了几个(open < n→ 还能放(
close已经用了几个)close < open→ 才能放)
len = open + close当前长度len == 2n→ 收集答案

class Solution {

public List generateParenthesis(int n) {

Listres=new ArrayList();

dfs(res,new StringBuilder(),0,0,n);

return res;

}

private void dfs(Listres,StringBuilder s,int left,int right,int n){

if(left+right==2*n){

res.add(s.toString());

return;

}

if(left<n){

s.append(‘(’);

dfs(res,s,left+1,right,n);

s.deleteCharAt(s.length()-1);

}

if(right<left){

s.append(‘)’);

dfs(res,s,left,right+1,n);

s.deleteCharAt(s.length()-1);

}

}

}

分隔回文串
给你一个字符串s,将s分割成一些 子串,使每个子串都是回文串。返回s所有可能的分割方案。
思路:
需要一个指针start:当前要处理的起始下标。

  • 从start出发,枚举结束位置end ∈ [start, n-1];
  • 如果s[start..end]是回文,就把它切成一段,然后递归处理end+1;
  • 如果start == n,说明整串被切完了,且每一段都经过回文检验 → 收集答案。

class Solution {

List<List>res=new ArrayList<>();

Listpath=new ArrayList<>();

char[] c;

int n;

public List<List> partition(String s) {

c=s.toCharArray();

n=s.length();

dfs(0);

return res;

}

private void dfs(int start){

if(start==n){

res.add(new ArrayList<>(path));

return;

}

for(int end=start;end<n;end++){

String temp=new String(c, start, end - start + 1);

if(ishuiwen(temp)){

path.add(temp);

dfs(end+1);

path.remove(path.size()-1);

}

}

}

private boolean ishuiwen(String s){

int n=s.length();

int l=0;

int r=n-1;

while(l<r){

if(s.charAt(l)!=s.charAt®)return false;

l++;

r–;

}

return true;

}

}

  1. 长度/下标 API:
  • 数组:arr.length(属性,无括号)
  • 字符串:s.length()、s.substring(l, r)(r 不含)
  • 集合:list.size()、list.remove(index)
  • char[] 截取:new String(ch, offset, count)(第三个是长度)
2.res.add(new ArrayList<>(path))为什么要拷贝

path是同一个对象,回溯过程中会不断 add/remove。如果写res.add(path),列表里存的是引用,最后你会得到一堆空列表或残缺数据。加new ArrayList<>(...)相当于当场拍一张快照存进去。这是所有「回溯收集 List<List<>>」题目的最高频 bug。

1.什么是 AOP

AOP是一种编程思想,它把那些与核心业务逻辑无关,但被多处模块共同依赖的代码(如日志、事务、权限)抽取出来,形成独立的“切面”,然后通过一种机制(织入)将这些切面应用到业务方法上。

核心目的:解耦。让业务代码只关心业务,让通用逻辑(切面)独立维护。

核心概念:

  • 切面(Aspect):通用逻辑的模块化,比如一个日志切面。

  • 连接点(Join Point):程序执行过程中的一个点,比如一个方法的调用。

  • 切入点(Pointcut):一个表达式,用来匹配哪些连接点需要被增强。

  • 通知(Advice):在切入点前后要执行的具体动作,如@Before、@After、@Around。

2.AOP实现方式:

  1. 基于代理的 AOP(Spring AOP):

    • JDK 动态代理:基于接口。要求目标类必须实现至少一个接口。代理类和目标类实现同一个接口。

    • CGLIB 动态代理:基于继承。通过生成目标类的子类来创建代理,因此无法代理final类或final方法。

    • Spring AOP 默认会根据目标类是否实现了接口来自动选择 JDK 或 CGLIB 代理。

  2. 基于 AspectJ 的 AOP:

    • AspectJ 是一个独立的、功能更强大的 AOP 框架。Spring 可以集成 AspectJ 的注解(如@Aspect、@Pointcut)和切点表达式语言,但底层实现仍然使用 Spring AOP 的动态代理机制。这是目前最常用的方式。

3.Spring AOP 的原理

Spring AOP 的底层原理是动态代理。

  1. 代理创建:当 Spring 容器启动时,它会扫描所有被@Aspect注解的类,并为那些需要被增强的目标 Bean 创建代理对象。

  2. 代理选择:

    • 如果目标类实现了接口,默认使用JDK 动态代理。

    • 如果目标类没有实现接口,则使用CGLIB 动态代理。

  3. 调用拦截:当调用代理对象的方法时,调用会被转发到InvocationHandler(JDK)或MethodInterceptor(CGLIB)。

  4. 通知执行:在调用处理器中,在目标方法执行前后插入相应逻辑(如开启事务、记录日志),然后通过反射调用目标方法。

4.Java 中的锁有哪些

可以从不同维度分类:

  • 按锁的实现:

    • synchronized:JVM 内置关键字,基于 Monitor 机制。

    • ReentrantLock:JUC 包下的 API,基于 AQS 实现。

  • 按锁的特性:

    • 公平锁 / 非公平锁:是否按请求顺序获取锁。

    • 可重入锁:同一线程可重复获取同一把锁。

    • 独享锁 / 共享锁:独享锁一次只能一个线程持有(如 ReentrantLock),共享锁可多个线程持有(如 ReadWriteLock 的读锁)。

    • 乐观锁 / 悲观锁:乐观锁假设无冲突,操作时检查(如 CAS);悲观锁假设总有冲突,操作前先加锁(如 synchronized)。

    • 偏向锁 / 轻量级锁 / 重量级锁:synchronized 的锁升级状态。

5.synchronized 加锁的流程

synchronized的锁状态会随着竞争情况升级,不可逆:

  1. 偏向锁:当只有一个线程访问时,锁会偏向该线程。在对象头中记录线程 ID,该线程再次进入时无需任何同步操作。

  2. 轻量级锁:当有第二个线程尝试获取锁时,偏向锁升级为轻量级锁。线程通过 CAS 自旋的方式尝试获取锁。

  3. 重量级锁:当自旋超过一定次数或第三个线程加入竞争时,轻量级锁升级为重量级锁。此时,未获取到锁的线程会被阻塞,进入操作系统层面的等待队列。

6.什么是锁消除

锁消除是 JVM 的即时编译器(JIT)在编译时进行的一种优化。

原理:JIT 编译器会通过逃逸分析判断一个锁对象是否只会被一个线程访问。如果确定锁对象不会“逃逸”出当前线程(即不会被其他线程访问),那么 JIT 就会认为这个锁是多余的,从而消除对应的加锁、解锁操作。

7.ReentrantLock 公平锁是怎么实现的

ReentrantLock 的公平锁是通过AQS(AbstractQueuedSynchronizer)实现的。

核心机制:

  1. CLH 队列:AQS 内部维护一个 FIFO 的双向队列(CLH 队列),所有等待获取锁的线程都会被包装成 Node 节点加入队列。

  2. 公平性判断:当线程尝试获取锁时,公平锁会先检查队列中是否有前驱节点。只有当当前线程是队列的第一个等待者时,才会尝试获取锁。

  3. 与非公平锁的区别:非公平锁在尝试获取锁时,会直接尝试 CAS 抢占,而不关心队列中是否有等待的线程,这可能导致“插队”。

8.CAS 的缺点是什么,如何避免

CAS(Compare-And-Swap)是一种乐观锁实现,包含三个操作数:内存位置当前值 V、预期原值 A、新值 B。当且仅当 V 的值等于 A 时,才将 V 更新为 B。

缺点:

  1. ABA 问题:一个值从 A 变成 B,又变回 A。CAS 检查时以为没变,但实际变了。

  2. 自旋开销大:如果 CAS 长时间失败,线程会一直自旋,消耗 CPU。

  3. 只能保证一个变量的原子操作:无法直接保证多个变量操作的原子性。

如何避免:

  1. ABA 问题:使用版本号或时间戳。Java 提供了AtomicStampedReference类,它内部维护了一个版本号,每次更新都会递增版本号。

  2. 自旋开销:可以设置自旋次数上限,超过后转为阻塞(如synchronized)。或者使用LongAdder等高并发场景下性能更好的类。

  3. 多变量原子性:可以封装成一个对象,使用AtomicReference来保证整个对象的原子性。或者直接使用锁。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/10/29 23:28:02

iMetaOmics第2卷第4期解读:组学工具化、多组学整合与单细胞常规化

前几天翻到 iMetaOmics期刊 第2卷第4期 在线正式发布 的消息&#xff0c;第一反应是去官网把目录拉下来扫了一遍。把几十篇文章的标题过完之后&#xff0c;几个比较明确的信号浮出来&#xff1a;组学研究的“工具化”趋势更明显了&#xff0c;宏基因组和代谢组的整合分析几乎成…

作者头像 李华
网站建设 2026/11/3 0:50:45

从醉茄内酯到内酯环:印度人参药效成分的生物合成解析

1. 为什么“印度人参”的药效&#xff0c;最后要落到一个环上1.1 先把名字正过来&#xff1a;它并不是人参如果只看商品名&#xff0c;你很难把“印度人参”和五加科的人参认成亲戚。它其实是茄科植物睡茄&#xff08;Withania somnifera&#xff09;&#xff0c;国外保健商品里…

作者头像 李华
网站建设 2026/10/31 2:24:45

光储并网动态功率分配:蓄电池与超级电容的分频控制实战

做光伏的人都知道&#xff0c;最难受的不是没有太阳&#xff0c;而是太阳跟你玩“打地鼠”。云一飘过来&#xff0c;功率唰地掉一半&#xff0c;云一过去&#xff0c;又嗖地窜上来。光伏板是不管这些的&#xff0c;它在那边“抖着腿晒太阳”&#xff0c;直流母线上的电压却是最…

作者头像 李华
网站建设 2026/10/30 20:09:48

AI驱动仓储数字孪生:Antigravity+Blender MCP进阶实战

接手这个项目时&#xff0c;我就在想一个问题&#xff1a;上篇我们把 Antigravity 接进 Blender MCP&#xff0c;等于给 AI 装了一双可以控制三维场景的手。但数字孪生如果只是把仓库建出来摆在那&#xff0c;那充其量是个好看的模型。这篇要做的&#xff0c;是把“模型”变成“…

作者头像 李华
网站建设 2026/11/2 10:32:43

从D状态到fork写时复制:Linux进程生命周期与内核机制全解析

1. 从top命令里的那一列说起&#xff1a;进程状态不是教科书上那张静态图上次写进程概念第一篇的时候&#xff0c;我从“什么是进程”讲到了“进程与程序的区别”&#xff0c;不少读者反馈说这些基础好理解&#xff0c;真正让人头疼的是状态。就拿最典型的场景来说&#xff1a;…

作者头像 李华