当前位置: 首页 > news >正文

java后端15问!

前言

最近一位粉丝去面试一个中厂,Java后端。他说,好几道题答不上来,于是我帮忙整理了一波答案

  1. G1收集器
  2. JVM内存划分
  3. 对象进入老年代标志
  4. 你在项目中用到的是哪种收集器,怎么调优的
  5. new对象的内存分布
  6. 局部变量的内存分布
  7. Synchronized和Lock的区别
  8. Synchronized原理
  9. 可重入是如何知道当前锁的拥有着的
  10. Spring用到的设计模式
  11. 说说SPI
  12. 排行榜怎么设计
  13. SpringBoot 中注解实现缓存用过没?实现原理是什么。
  14. 深分页优化
  15. Redis分布式锁如何进一步提升性能

1. 说说G1收集器

G1(Garbage-First)收集器是 Java 虚拟机中的一种垃圾收集器。它于 JDK 7 中首次引入,并在后续版本中不断改进优化。

  • 可以使用 -XX:+UseG1GC 开启它。这个选项告诉 JVM 在运行时使用 G1 垃圾收集器来管理堆内存。
  • G1(Garbage-First)收集器的核心原则之一就是“首先收集尽可能多的垃圾”,即优先回收那些包含最多垃圾的区域。这个原则是与CMS收集器有所不同的,CMS主要关注于尽可能减少应用程序的停顿时间
  • G1 收集器会将 Java 堆划分为多个大小相等的区域(Region),然后根据当前堆内存的使用情况,选择性地进行垃圾回收。
  • 当 G1 收集器决定进行Full GC时,它会执行一次 Full GC(Full GC),这时整个应用程序将会暂停(STW)。但在Mixed GC中,G1 收集器会在某些情况下选择部分年轻代分区和部分老年代分区进行回收,这样一来,即使不是整个堆内存的垃圾回收,仍然可能会导致一些暂停,但相对于 Full GC,这种暂停时间会更短。
  • 适用于大内存、对停顿时间敏感、需要高吞吐量的应用场景。

2. JVM内存划分

Java 虚拟机(JVM)的内存分为多个区域,每个区域都有不同的作用和管理方式。JVM 内存划分的主要区域:

图片

  • 堆(Heap):堆是 JVM 中最大的一块内存区域,用于存储对象实例和数组。堆内存由所有线程共享,是垃圾收集器主要管理的区域。
  • 程序计数器(Program Counter):程序计数器是一块较小的内存空间,它是线程私有的,用于存储当前线程正在执行的字节码指令的地址。在多线程环境下,每个线程都有一个独立的程序计数器,以保证线程切换后能够恢复到正确的执行位置。
  • 虚拟机栈(Java Virtual Machine Stacks):虚拟机栈也是线程私有的,用于存储方法执行过程中的局部变量、方法参数、中间结果等数据。每个方法在执行时都会创建一个栈帧,栈帧包含了方法的局部变量表、操作数栈、动态链接、方法返回地址等信息。
  • 本地方法栈(Native Method Stacks):本地方法栈与虚拟机栈类似,用于执行本地方法(Native Method)时的数据存储。与虚拟机栈一样,本地方法栈也是线程私有的。
  • 方法区(Method Area):方法区用于存储类信息、常量、静态变量和即时编译器编译后的代码等数据。在jdk7及以前,习惯上把方法区,称为永久代。jdk8开始,使用元空间取代了永久代。本质上,方法区和永久代并不等价。通过-XX:Permsize来设置永久代初始分配空间。可以使用参数 -XX:MetaspaceSize 和 -XX:MaxMetaspaceSize指定默认值依赖于平台。
  • 运行时常量池(Runtime Constant Pool):运行时常量池是方法区的一部分,用于存储编译时生成的字面量常量和符号引用。与类文件中的常量池(Constant Pool)相对应,运行时常量池具有动态性,可以在运行时动态地添加、修改常量。
  • 直接内存(Direct Memory):直接内存不是 JVM 内存的一部分,但是在一些情况下会被 JVM 使用。直接内存是通过使用 java.nio 包中的类来申请和释放的,它允许 JVM 在堆外分配内存,可以提高 I/O 操作的效率。

3. 对象进入老年代标志

图片

  • 对象年龄达到阈值:对象在 Java 堆中的存活时间通常会通过对象年龄(Age)来衡量。在某些垃圾收集器中,当对象经过多次垃圾收集后仍然存活,并且达到了一定的年龄阈值,就会被晋升到老年代。年龄阈值可以通过 JVM 参数进行调整。
  • 大对象:大对象通常指的是占用大量内存空间的对象,例如数组或者很大的字符串。在一些垃圾收集器中,为了避免在新生代中频繁复制大对象,会直接将大对象分配在老年代中。
  • 长期存活的对象:一些长期存活的对象,例如长期存在的线程、静态变量等,有可能直接被分配到老年代中。
  • 晋升失败:当新生代中的对象经过多次垃圾回收仍然存活,并且新生代内存不足以容纳这些存活对象时,会发生一次晋升失败,这时一部分存活对象可能会被直接晋升到老年代。

通常情况下,老年代用于存放长期存活的对象,以减少垃圾收集的频率和提高垃圾回收的效率。

4. 你在项目中用到的是哪种收集器,怎么调优的

我列举了常见的垃圾收集器以及调优策略:

串行收集器(Serial Garbage Collector):

  • 适用于单核 CPU 或小型应用场景。
  • 调优参数:-XX:+UseSerialGC

并行收集器(Parallel Garbage Collector):

  • 适用于多核 CPU,通过并行收集来提高垃圾回收效率。
  • 调优参数:-XX:+UseParallelGC

并发标记-清除收集器(Concurrent Mark-Sweep Garbage Collector,CMS GC):

  • 适用于对系统停顿时间敏感的应用场景。
  • 调优参数:-XX:+UseConcMarkSweepGC

G1 收集器(Garbage-First Garbage Collector):

  • 适用于大内存、对停顿时间敏感、需要高吞吐量的应用场景。
  • 调优参数:-XX:+UseG1GC

ZGC 和 Shenandoah(JDK 11+):

  • 适用于超大内存、对停顿时间极为敏感的应用场景。
  • 调优参数:-XX:+UseZGC(ZGC)、-XX:+UseShenandoahGC(Shenandoah)

当然,调优的具体策略会根据应用的特点和需求来定,可以通过以下一些常见的调优手段来改进垃圾收集器的性能:

  • 调整堆大小(-Xms、-Xmx)以及新生代与老年代的比例(-XX:NewRatio、-XX:SurvivorRatio)。
  • 设置垃圾收集器的参数,如并行收集器的线程数(-XX:ParallelGCThreads)、并发标记-清除收集器的初始标记阶段并发线程数(-XX:ConcGCThreads)等。
  • 设置垃圾收集器的触发条件,如新生代垃圾收集的触发条件(-XX:MaxNewSize、-XX:NewThreshold)等。
  • 监控和分析 GC 日志,根据应用的实际情况进行优化。选择合适的 GC 日志分析工具,如GCViewer、GCEasy等,进行进一步的性能分析和优化。

5. new对象的内存分布

在 Java 中,当使用 new 关键字创建一个对象时,对象在内存中的基本结构通常由对象头、实例数据和填充组成。

  • 对象头(Object Header):对象头存储了对象的元数据信息,如哈希码、对象锁状态、GC 相关信息等。对象头的结构和大小在不同的 JVM 实现中可能会有所不同,但通常包括一些固定的字段。
  • 实例数据(Instance Data):实例数据包含了对象的实际数据,即对象中的成员变量的值。这些数据根据对象的类定义来确定,包括各种类型的字段和对象引用等。
  • 填充(Padding):填充是为了满足内存对齐的需要而添加的额外字节。内存对齐可以提高内存访问的效率,一些 JVM 可能会在对象的实例数据后添加填充字节,使得对象的起始地址能够对齐到某个特定的边界。

6. 局部变量的内存分布

栈帧结构:

  • 栈帧由三部分组成:局部变量表(Local Variable Table)、操作数栈(Operand Stack)和帧数据(Frame Data)。
  • 局部变量表用于存储方法参数和方法内部定义的局部变量。
  • 操作数栈用于存储方法执行过程中的操作数。
  • 帧数据包含了方法的异常处理信息、方法返回地址等。

局部变量表:

  • 局部变量表是一个数组,用于存储方法参数和方法内部定义的局部变量。
  • 局部变量表中的每个元素都可以存储一个数据值,数据类型可以是基本数据类型或者引用类型。
  • 局部变量表中的变量只在方法执行期间有效,当方法执行结束后,局部变量表所占用的内存空间会被释放。

局部变量的存储位置:

  • 对于基本数据类型的局部变量,它们的值直接存储在局部变量表中。
  • 对于引用类型的局部变量,局部变量表中存储的是对象的引用,而对象的实际数据存储在堆内存中。

局部变量的生命周期:

  • 局部变量的生命周期与方法的执行周期相同,当方法执行结束后,局部变量表所占用的内存空间会被释放。
  • 局部变量的生命周期也可能会被延长,比如局部变量被捕获到一个匿名内部类中,那么该局部变量的生命周期会与匿名内部类的生命周期保持一致。

7.Synchronized和ReenTrantLock的区别

  • Synchronized是依赖于JVM实现的,而ReenTrantLock是API实现的。
  • 在Synchronized优化以前,synchronized的性能是比ReenTrantLock差很多的,但是自从Synchronized引入了偏向锁,轻量级锁(自旋锁)后,两者性能就差不多了。
  • Synchronized的使用比较方便简洁,它由编译器去保证锁的加锁和释放。而ReenTrantLock需要手工声明来加锁和释放锁,最好在finally中声明释放锁。
  • ReentrantLock可以指定是公平锁还是⾮公平锁。⽽synchronized只能是⾮公平锁。
  • ReentrantLock可响应中断、可轮回,而Synchronized是不可以响应中断的

8.Synchronized原理

synchronized是Java中的关键字,是一种同步锁。synchronized关键字可以作用于方法或者代码块。

一般面试时。可以这么回答:

  • 反编译后,monitorenter、monitorexit、ACC_SYNCHRONIZED
  • monitor监视器
  • Java Monitor 的工作机理
  • 对象与monitor关联

8.1 monitorenter、monitorexit、ACC_SYNCHRONIZED

  • 如果synchronized作用于代码块,反编译可以看到两个指令:monitorenter、monitorexit,JVM使用monitorenter和monitorexit两个指令实现同步;
  • 如果作用synchronized作用于方法,反编译可以看到ACCSYNCHRONIZED标记,JVM通过在方法访问标识符(flags)中加入ACCSYNCHRONIZED来实现同步功能。
  • 同步代码块是通过monitorenter和monitorexit来实现,当线程执行到monitorenter的时候要先获得monitor锁,才能执行后面的方法。当线程执行到monitorexit的时候则要释放锁。
  • 同步方法是通过中设置ACCSYNCHRONIZED标志来实现,当线程执行有ACCSYNCHRONIZED标志的方法,需要获得monitor锁。每个对象都与一个monitor相关联,线程可以占有或者释放monitor。

8.2 monitor监视器

monitor是什么呢?操作系统的管程(monitors)是概念原理,ObjectMonitor是它的原理实现。

在Java虚拟机(HotSpot)中,Monitor(管程)是由ObjectMonitor实现的,其主要数据结构如下:

ObjectMonitor() {_header       = NULL;_count        = 0; // 记录个数_waiters      = 0,_recursions   = 0;_object       = NULL;_owner        = NULL;_WaitSet      = NULL;  // 处于wait状态的线程,会被加入到_WaitSet_WaitSetLock  = 0 ;_Responsible  = NULL ;_succ         = NULL ;_cxq          = NULL ;FreeNext      = NULL ;_EntryList    = NULL ;  // 处于等待锁block状态的线程,会被加入到该列表_SpinFreq     = 0 ;_SpinClock    = 0 ;OwnerIsThread = 0 ;}

ObjectMonitor中几个关键字段的含义如图所示:

图片

8.3 Java Monitor 的工作机理

图片

  • 想要获取monitor的线程,首先会进入_EntryList队列。
  • 当某个线程获取到对象的monitor后,进入Owner区域,设置为当前线程,同时计数器count加1。
  • 如果线程调用了wait()方法,则会进入WaitSet队列。它会释放monitor锁,即将owner赋值为null,count自减1,进入WaitSet队列阻塞等待。
  • 如果其他线程调用 notify() / notifyAll() ,会唤醒WaitSet中的某个线程,该线程再次尝试获取monitor锁,成功即进入Owner区域。
  • 同步方法执行完毕了,线程退出临界区,会将monitor的owner设为null,并释放监视锁。

8.4 对象与monitor关联

图片

  • 在HotSpot虚拟机中,对象在内存中存储的布局可以分为3块区域:对象头(Header),实例数据(Instance Data)和对象填充(Padding)。
  • 对象头主要包括两部分数据:Mark Word(标记字段)、Class Pointer(类型指针)。
  • Mark Word 是用于存储对象自身的运行时数据,如哈希码(HashCode)、GC分代年龄、锁状态标志、线程持有的锁、偏向线程 ID、偏向时间戳等。
  • 重量级锁,指向互斥量的指针。其实synchronized是重量级锁,也就是说Synchronized的对象锁,Mark Word锁标识位为10,其中指针指向的是Monitor对象的起始地址。

9.可重入是如何知道当前锁的拥有着的

比如,ReentrantLock 是可重入的锁。ReentrantLock 类实现了可重入锁的概念,允许同一个线程在持有锁的情况下多次获取同一个锁,而不会被阻塞。

在 ReentrantLock 中,每个锁都关联着一个持有计数器和一个拥有者线程。当一个线程首次获取锁时,持有计数器会增加;当该线程再次获取锁时,持有计数器会继续增加。每次释放锁时,计数器会相应减少。只有当持有计数器减为零时,锁才会完全释放,其他线程才有机会获取锁。

这样一来,当线程尝试获取锁时,它会检查当前锁的持有计数器以及拥有者线程。如果锁未被任何线程持有,或者当前线程是锁的拥有者,那么锁将立即分配给当前线程。否则,当前线程会被阻塞,直到锁被释放。

10.Spring用到的设计模式

  • 单例模式(Singleton Pattern):Spring 中的 Bean 默认是单例的,即每个 Bean 只有一个实例。这种方式可以提高性能并减少资源消耗。
  • 工厂模式(Factory Pattern):Spring 使用工厂模式来创建和管理 Bean。它提供了几种不同类型的工厂,比如 BeanFactory 和 ApplicationContext,用于创建和管理 Bean 对象。
  • 代理模式(Proxy Pattern):Spring AOP(面向切面编程)功能基于代理模式实现。它允许通过在运行时为目标对象创建代理对象来添加横切关注点(如日志记录、性能监控等)。
  • 装饰者模式(Decorator Pattern):Spring 中的 BeanPostProcessor 接口就是一个装饰器模式的例子。它允许在 Bean 初始化过程中动态地添加新的功能。
  • 观察者模式(Observer Pattern):Spring 的事件机制就是基于观察者模式实现的。它允许 Bean 发布事件,其他 Bean 可以注册监听器来响应这些事件。
  • 策略模式(Strategy Pattern):Spring 的 IOC(控制反转)和 DI(依赖注入)功能基于策略模式实现。它允许将不同的实现注入到一个接口或抽象类中,以便在运行时选择不同的行为。
  • 模板模式(Template Pattern):Spring 的 JdbcTemplate 和 HibernateTemplate 等模板类就是模板模式的应用。它们封装了一些常见的操作,使开发者可以通过简单的方法调用来执行数据库操作。
  • 适配器模式(Adapter Pattern):Spring 的 AOP 功能和 Spring MVC 框架都使用了适配器模式。它们允许将现有的类与新的接口进行适配,以便实现新的功能。
  • 建造者模式(Builder Pattern):Spring 中的 BeanDefinitionBuilder 和 BeanFactoryBuilder 等构建器模式的应用。它们用于构建复杂的对象,并且允许逐步设置对象的属性。

11.聊聊SPI

SPI,其实就是​​Service Provider Interface​​,是Java提供的一种机制,用于在运行时动态装载实现模块,使得应用程序能够扩展、替换特定的服务或实现。

SPI的工作原理主要包括以下几个关键点:

  • 接口定义:首先,需要定义一个接口,该接口定义了一组操作或服务。这个接口通常由Java核心库或者第三方库提供。
  • 服务提供者:其次,可以有多个服务提供者来实现这个接口。这些服务提供者通常是独立的模块或者库,它们在自己的jar包中提供了实现。
  • 配置文件:在Java中,SPI通过在META-INF/services目录下的特定配置文件中指定实现类的方式来实现动态装载。具体来说,SPI机制要求服务提供者在这个目录下创建一个以接口全限定名为文件名的文件,文件中列出了具体的实现类名。
  • 动态加载:当应用程序需要某个服务时,Java运行时会动态加载配置文件中指定的实现类,并实例化它们。这种机制使得应用程序能够在不修改源代码的情况下灵活地替换或扩展特定的服务实现。

在实际应用中,我们可以利用SPI来实现插件化架构、模块化开发等,从而提高代码的可维护性和可扩展性。

12.排行榜怎么设计

可以考虑:数据库的order by、或者Redis 的zset

大家可以看下我的这篇文章哈:

​​如何设计一个排行榜​​

对于游戏排行榜,如果数据量达到亿万级别,需要考虑的确实是分桶策略,而桶排序则是分桶策略的一种可能实现方式之一。

桶排序是一种基于这种分桶策略的排序算法,它将数据划分到若干个有序的桶中,然后分别对每个桶中的数据进行排序,最后将所有桶中的数据按照顺序合并起来,得到排好序的结果。

在游戏排行榜系统中,可以根据玩家的分数范围、等级、地区等因素来设计分桶策略,将玩家数据划分到不同的桶中。这样可以使得每个桶内的数据量相对较小,提高了排序的效率。

13.SpringBoot 中注解实现缓存用过没?实现原理是什么。

常见的缓存注解包括 ​​@Cacheable、@CachePut、@CacheEvict ​​等。这些注解的实现原理基于​​Spring​​提供的缓存抽象。

是的,Spring Boot 中的缓存注解常用于提升系统性能,减少重复计算,常见的缓存注解包括 @Cacheable、@CachePut、@CacheEvict 等。这些注解的实现原理基于 Spring Framework 提供的缓存抽象。

实现原理:

  1. 代理机制
  • Spring Boot 使用 AOP(面向切面编程)的方式,在运行时动态地为带有缓存注解的方法生成代理对象。
  • 当调用带有缓存注解的方法时,实际上是调用代理对象的方法。
  1. 缓存管理器
  • Spring Boot 提供了多种缓存管理器的实现,比如基于 ConcurrentHashMap 的 SimpleCacheManager、基于 Ehcache的缓存管理器。

  • 缓存管理器负责真正地操作缓存,将数据存储到缓存中或者从缓存中获取数据。

  1. 缓存注解

  • @Cacheable:标记在方法上,表示方法的返回值将会被缓存,当方法被调用时,首先从缓存中查找数据,如果缓存中存在数据,则直接返回,否则执行方法并将结果存储到缓存中。

  • @CachePut:标记在方法上,表示方法的返回值将会被存储到缓存中,即使缓存中已经存在相同 key 的数据,也会重新存储。

  • @CacheEvict:标记在方法上,表示清除缓存中的数据,可以根据条件来清除指定的缓存数据。

  1. 缓存 key 的生成

  • 默认情况下,缓存 key 是由方法的参数组成的,默认的 key 生成器是 SimpleKeyGenerator。

  • 可以通过自定义 key 生成器来生成复杂的缓存 key。

  1. 缓存注解的执行流程

  • 当方法被调用时,首先会根据方法参数生成缓存 key。

  • 然后从缓存中根据缓存 key 查找数据,如果找到则返回,否则执行方法并将结果存储到缓存中。

  • 在 @CachePut 和 @CacheEvict 注解中,会根据条件清除缓存中的数据或者将数据存储到缓存中。

14.深分页优化

我们可以通过减少回表次数来优化。一般有标签记录法和延迟关联法。

14.1 标签记录法

就是标记一下上次查询到哪一条了,下次再来查的时候,从该条开始往下扫描。就好像看书一样,上次看到哪里了,你就折叠一下或者夹个书签,下次来看的时候,直接就翻到啦。

假设上一次记录到100000,则SQL可以修改为:

select  id,name,balance FROM account where id > 100000 limit 10;

这样的话,后面无论翻多少页,性能都会不错的,因为命中了id索引。但是这种方式有局限性:需要一种类似连续自增的字段。

14.2 延迟关联法

延迟关联法,就是把条件转移到主键索引树,然后减少回表。假设原生SQL是这样的的,其中id是主键,create_time是普通索引

select id,name,balance from account where create_time> '2020-09-19' limit 100000,10;

使用延迟关联法优化,如下:

select  acct1.id,acct1.name,acct1.balance FROM account acct1 INNER JOIN 
(SELECT a.id FROM account a WHERE a.create_time > '2020-09-19' limit 100000, 10) 
AS acct2 on acct1.id= acct2.id;

优化思路就是,先通过idx_create_time二级索引树查询到满足条件的主键ID,再与原表通过主键ID内连接,这样后面直接走了主键索引了,同时也减少了回表。

15.分布式锁如何进一步提升性能,答了Redis的实现思路好像不是面试官想听的

redis分布式锁,我觉得可以从一下这几个方向来回答:

  • Pipeline 批量操作:使用 Redis 的 Pipeline 功能可以将多个 Redis 命令打包发送给服务器,减少网络延迟,提高性能。在获取锁、释放锁等操作时,可以考虑使用 Pipeline 来批量执行多个命令。
  • Lua 脚本:Redis 支持 Lua 脚本,可以将多个操作封装在一个脚本中,在服务器端原子性地执行,减少了网络通信的开销。可以将获取锁和释放锁的逻辑封装在 Lua 脚本中,以提高性能。
  • 降级策略:在高并发情况下,可以考虑引入降级策略,当获取锁失败时,可以使用备用方案或者默认值来处理,而不是一直等待锁的释放。
  • 监控和优化:通过监控 Redis 的性能指标,如连接数、命令执行时间等,可以及时发现性能瓶颈,并进行优化。可以通过 Redis 的监控工具或者第三方监控工具来实现监控。
  • 合理设置锁的过期时间:根据业务场景的特点和需求,合理设置锁的过期时间,避免锁被长时间占用而影响系统性能。可以根据操作的耗时和锁的竞争情况来动态调整锁的过期时间。
  • 使用 Redlock 算法:Redlock 是一种基于多个 Redis 节点的分布式锁算法,可以提高分布式锁的可靠性和性能。可以考虑使用 Redlock 算法来实现分布式锁。

相关文章:

java后端15问!

前言 最近一位粉丝去面试一个中厂,Java后端。他说,好几道题答不上来,于是我帮忙整理了一波答案 G1收集器JVM内存划分对象进入老年代标志你在项目中用到的是哪种收集器,怎么调优的new对象的内存分布局部变量的内存分布Synchroniz…...

OmniPlan Pro 4 for Mac中文激活版:项目管理的新选择

OmniPlan Pro 4 for Mac作为一款专为Mac用户设计的项目管理软件,为用户提供了全新的项目管理体验。其直观易用的界面和强大的功能特性,使用户能够轻松上手并快速掌握项目管理要点。 首先,OmniPlan Pro 4 for Mac支持自定义视图,用…...

二叉树的广度优先遍历 - 华为OD统一考试(D卷)

OD统一考试(D卷) 分值: 200分 题解: Java / Python / C++ 题目描述 有一棵二叉树,每个节点由一个大写字母标识(最多26个节点)。 现有两组字母,分别表示后序遍历(左孩子->右孩子->父节点)和中序遍历(左孩子->父节点->右孩子)的结果,请输出层次遍历的结…...

代码随想录-算法训练营day31【贪心算法01:理论基础、分发饼干、摆动序列、最大子序和】

代码随想录-035期-算法训练营【博客笔记汇总表】-CSDN博客 第八章 贪心算法 part01● 理论基础 ● 455.分发饼干 ● 376. 摆动序列 ● 53. 最大子序和 贪心算法其实就是没有什么规律可言,所以大家了解贪心算法 就了解它没有规律的本质就够了。 不用花心思去研究其…...

如何使用Transformer-TTS语音合成模型

1、技术原理及架构图 ​ Transformer-TTS主要通过将Transformer模型与Tacotron2系统结合来实现文本到语音的转换。在这种结构中,原始的Transformer模型在输入阶段和输出阶段进行了适当的修改,以更好地处理语音数据。具体来说,Transformer-TT…...

【Python】JSON数据的使用

一、JSON JSON是什么: JSON(JavaScript Object Notation)是一种轻量级的数据交换格式,它以易于理解和生成的文本格式来描述数据对象。JSON最初是由Douglas Crockford在2001年提出的,它的设计受到了JavaScript对象字面量…...

C语言头文件的引入使用<>和““有什么区别

在C语言中&#xff0c;引入头文件时使用<>和""有以下主要区别&#xff1a; 搜索路径不同&#xff1a; 当使用#include <filename.h>时&#xff0c;编译器会首先在系统目录中搜索头文件。这些系统目录通常包含了标准库的头文件&#xff0c;如stdio.h、std…...

Qt 类的设计思路详解

Qt 是一个跨平台的 C++ 应用程序开发框架,它提供了丰富的类库和工具,用于开发图形用户界面、网络应用、数据库集成和文件 I/O 等功能。Qt 的设计思路涉及到诸多方面,包括跨平台性、模块化、可扩展性、性能等。本文将从这些方面详细说明 Qt 类的设计思路。 1. 跨平台性 Qt 最…...

五一超级课堂---Llama3-Tutorial(Llama 3 超级课堂)---第一节 Llama 3 本地 Web Demo 部署

课程文档&#xff1a; https://github.com/SmartFlowAI/Llama3-Tutorial 课程视频&#xff1a; https://space.bilibili.com/3546636263360696/channel/collectiondetail?sid2892740&spm_id_from333.788.0.0 操作平台&#xff1a; https://studio.intern-ai.org.cn/consol…...

Redis20种使用场景

Redis20种使用场景 1缓存2抽奖3Set实现点赞/收藏功能4排行榜5PV统计&#xff08;incr自增计数&#xff09;6UV统计&#xff08;HeyperLogLog&#xff09;7去重&#xff08;BloomFiler&#xff09;8用户签到&#xff08;BitMap&#xff09;9GEO搜附近10简单限流11全局ID12简单分…...

vue3获取原始值

在 Vue 3 中&#xff0c;_rawValue 是 ref 内部的一个属性&#xff0c;它用来存储 ref 的原始值&#xff0c;也就是未经响应式处理的值。这个属性主要用于 Vue 的内部逻辑&#xff0c;以帮助区分 ref 的当前值 (value) 和原始输入值 (_rawValue)。对于大多数开发者来说&#xf…...

“感恩遇到你,郭护士!”佛山市一医院 护士回家途中救了位老奶奶

“感恩遇见你&#xff0c;我感谢郭护士关爱长者、热心助人的高尚行为……”看着信件上感谢的话语&#xff0c;郭琳玲的内心感动不已。而这一封亲笔手写的感谢信&#xff0c;是来自一位将近八十岁的老奶奶。 郭琳玲是佛山市第一人民医院创伤重症功能神经外科的一名护士。4月30日…...

Java面试常见问题

操作系统 1.Q: 在操作系统中&#xff0c;什么时候会发生用户态到内核态的切换 A: 操作系统中&#xff0c;用户态和内核态是两种不同的权限级别&#xff0c;他们对应着不同的执行环境和执行权限。用户态事指程序在一般的运行情况下的的级别&#xff0c;它具有别较低的权限级别&…...

概率论 科普

符号优先级 概率公式中一共有三种符号&#xff1a;分号 ; 、逗号 , 、竖线 | 。 ; 分号代表前后是两类东西&#xff0c;以概率P(x;θ)为例&#xff0c;分号前面是x样本&#xff0c;分号后边是模型参数。分号前的 表示的是这个式子用来预测分布的随机变量x&#xff0c;分号后的…...

全面解读快递查询API接口,帮你轻松查询快递物流信息

随着电子商务的快速发展&#xff0c;快递业务正变得越来越重要。无论是买家还是卖家&#xff0c;都希望能够及时了解自己的快递物流信息&#xff0c;以便更好地掌控商品的运输过程。而现在&#xff0c;通过快递查询API接口&#xff0c;我们可以实现快速、准确地查询几百家国内快…...

【图书推荐】《JSP+Servlet+Tomcat应用开发从零开始学(第3版)》

本书目的 系统讲解JSPServletTomcat开发技术&#xff0c;帮助读者用最短的时间掌握Java Web应用开发技能。 内容简介 本书全面系统地介绍JSPServletTomcat开发中涉及的相关技术要点和实战技巧。本书内容讲解循序渐进&#xff0c;结合丰富的示例使零基础的读者能够熟练掌握JSP…...

C++容器——set

set容器 是一个关联容器&#xff0c;按一定的顺序存储一组唯一的元素。 set容器中的元素会根据元素的值自动进行排序&#xff0c;并且不允许包含重复的元素&#xff0c;基于二叉树实现的。 特点&#xff1a; 唯一性&#xff1a; set容器中的元素是唯一的&#xff0c;即容器中…...

.NET WebService \ WCF \ WebAPI 部署总结 以及 window 服务 调试

一、webservice 部署只能部署IIS上&#xff0c; 比较简单&#xff0c;就不做说明了 二、 WCF 部署 1 部署到IIS 跟部署 webservice 部署方法一样的 wcf 部署2 部署到控制台 要以管理员运行vs&#xff0c;或者 管理员运行 控制台的exe 在控制器项目中 创建IUserInfoService 接口…...

Centos系统实用运维命令记录(持续更新)

本文记录Centos服务器常用的运维命令&#xff0c;备忘 查询当前内存占用最高(前10)的进程列表和占用比例&#xff0c;进程ID ps -eo pid,comm,%mem,cmd --sort-%mem | head -n 11注: 内存警报时定位问题时非常有用 查询占用某个端口号的进程id lsof -i :9000注: 后面的9000…...

大势模方在修模过程中,如何导入su单体模型?

答&#xff1a;在单体化界面右键即可显示导入入口&#xff0c;若仍不可行&#xff0c;需要换最新版dv 模方是一款针对实景三维模型的冗余碎片、水面残缺、道路不平、标牌破损、纹理拉伸模糊等共性问题研发的实景三维模型修复编辑软件。模方4.1新增自动单体化建模功能&#xff…...

uniapp百度地图聚合

// loadBMap.js ak 百度key export default function loadBMap(ak) {return new Promise((resolve, reject) > {//聚合API依赖基础库,因此先加载基础库再加载聚合APIasyncLoadBaiduJs(ak).then(() > {// 调用加载第三方组件js公共方法加载其他资源库// 加载聚合API// Ma…...

nginx的应用部署nginx

这里写目录标题 nginxnginx的优点什么是集群常见的集群什么是正向代理、反向代理、透明代理常见的代理技术正向代理反向代理透明代理 nginx部署 nginx nginx&#xff08;发音同enginex&#xff09;是一款轻量级的Web服务器/反向代理服务器及电子邮件&#xff08;IMAP/POP3&…...

Centos固定静态ip地址

这里我用的是Vmware虚拟机搭建的三台机器 进入 cd /etc/sysconfig/network-scripts然后使用 ip addr命令&#xff0c;查看自己虚拟机的以太网地址。 我这里是ens33 上面的第一个选项是本地环回地址&#xff0c;不用管它 然后查看刚刚进入的network-scripts目录下的文件 找到…...

豆芽机置入语音芯片WTN6040-8S:开启智能生活新篇章,让豆芽制作更便捷有趣

豆芽机的开发背景&#xff1a; 豆芽作为一种营养丰富、味道鲜美的食品&#xff0c;深受广大消费者的喜爱。然而&#xff0c;传统的豆芽生产过程繁琐&#xff0c;需要耗费大量的时间和人力&#xff0c;且存在生产效率低、质量不稳定等问题。随着人们生活节奏的加快和对健康饮食的…...

BLIP2预研笔记

0. 前言 文章是公司内部分享学习写的预研报告&#xff0c;里面有小部分文段是直接从网上借鉴的&#xff0c;侵删 1. 任务和方法历史进化&#xff1a; 在大模型等类似的预训练模型的方式&#xff08;以包含“预训练阶段”等n阶段训练方式为特色&#xff09;为主流之前&#xf…...

安卓开发问题:安卓Ble出现动态鉴权失败以及扫描设备一直进入不了的问题

问题1描述 1、安卓12需要动态鉴权 // 鉴权函数 requestPermissions(permissionsList.toArray(strings), MyConstants.REQUEST_CODE_PERMISSIONS);但是在鉴权回调函数中如Manifest.permission.BLUETOOTH_SCAN、Manifest.permission.BLUETOOTH_CONNECT一直显示失败&…...

DSP ARM FPGA 实验箱_音频处理_滤波操作教程:3-9 音频信号的滤波实验

一、实验目的 掌握Matlab辅助设计滤波器系数的方法&#xff0c;并实现音频混噪及IIR滤波器滤除&#xff0c;并在LCD上显示音频信号的FFT计算结果。 二、实验原理 音频接口采用的是24.576MHz&#xff08;读兆赫兹&#xff09;晶振&#xff0c;实验板上共有3个音频端口&#x…...

Rust多线程交叉打印+Send Sync特征讲解

导航 Rust多线程交叉打印Send Sync特征讲解 一、Rust多线程交叉打印二、Send Sync 特征讲解 Rust多线程交叉打印Send Sync特征讲解 一、Rust多线程交叉打印 先说背景有两个线程&#xff0c;分别为0号线程和1号线线程两个线程交叉打印共享值&#xff0c;并将共享值1当标志为fa…...

C#爬虫爬取某东商品信息

&#x1f3c6;作者&#xff1a;科技、互联网行业优质创作者 &#x1f3c6;专注领域&#xff1a;.Net技术、软件架构、人工智能、数字化转型、DeveloperSharp、微服务、工业互联网、智能制造 &#x1f3c6;欢迎关注我&#xff08;Net数字智慧化基地&#xff09;&#xff0c;里面…...

【Stylus详解与引入】

文章目录 Stylus详解与引入一、Stylus简介二、Stylus的特性1. 变量2. 嵌套规则3. 混合&#xff08;Mixins&#xff09;4. 函数5. 条件语句和循环 三、Stylus的引入与配置1. 安装Stylus和stylus-loader2. 配置Webpack3. 在Vue项目中使用Stylus4. 编译Stylus代码四、Stylus的性能…...

表白时刻网站/济南百度公司

#css基本语法及页面引用 ##css基本语法 css的定义方法是&#xff1a; 选择器 { 属性:值; 属性:值; 属性:值;} 选择器是将样式和页面元素关联起来的名称&#xff0c;属性是希望设置的样式属性每个属性有一个或多个值。代码示例&#xff1a; div{ width:100px; height:100px; …...

网站推广托管/福州seo结算

请创建一个一维整型数组用来存储待排序关键码&#xff0c;关键码从数组下标为1的位置开始存储&#xff0c;下标为0的位置不存储关键码。输入关键码的个数&#xff0c;以及各个关键码&#xff0c;采用起泡排序的方法对关键码数组进行排序&#xff0c;输出每轮比较的过程。 输入描…...

男人和女人做受吃母乳视频网站免费/南宁百度seo公司

python 中时间格式转换 import time, datetime时间戳 时间戳转时间 timestamp time.time() # 当时时间下的时间戳 zerotimestamp datetime.datetime.utcfromtimestamp(time.time()) # 当时时间戳下巴黎时间计时的时间戳在时间戳上利用秒计时来实现时间的加减&#xff0c; …...

手机网站开发计划/seo推广是什么意思

#define&#xff0c;typedef&#xff0c;struct&#xff0c;enmu是我们阅读单片机底层代码时最经常碰到几个概念。 首先分开解释一下 宏定义#define与定义别名typedef&#xff0c;它俩一起说&#xff0c;因为它俩的功能十分相似&#xff0c;具体的的用法不说了&#xff0c;注…...

花木网站模版/永久免费个人网站申请注册

1 FFmpeg录屏以及录音的命令 最近需要用到FFmpeg录制声卡中的声音&#xff0c;在cmd.exe的命令行中使用正常的录音命令&#xff1a; ffmpeg -f dshow -i audio"virtual-audio-capturer" -acodec aac f:\temp.aac是可以实现录制的 然后按照官方的按Q键暂停录制 也…...

网站开发的最后五个阶段/网站建设方案及报价

有朋友会问“为什么我的在每天晚上10点钟运行的非常缓慢&#xff1f;”。有经验的朋友会想到为CBO提供了自动收集数据库对象统计信息的功能&#xff0c;称之为“”。与之对应的Job正是在周一至周五的晚上10:00到第二天早上的6:00以及周六周日全天这个中来完成的。我们探索一下A…...