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 算法来实现分布式锁。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/605843.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

中职大数据专业介绍:大数据技术应用

近年来,人工智能在经济发展、社会进步、国际政治经济格局等方面已经产生重大而深远的影响。规划纲要对“十四五”及未来十余年我国人工智能的发展目标、核心技术突破、智能化转型与应用,以及保障措施等多个方面都作出了部署。 据2020年全国教育事业发展统…

运用分支结构与循环结构写一个猜拳小游戏

下面我们运用平常所学的知识来写一个小游戏,这样能够加强我们学习的趣味性,并且能够更加的巩固我们所学的知识。 游戏代码: 直接放代码:(手势可以使用数字来代替,比如0对应石头,1对应剪刀&…

Qexo:让你的静态博客动起来

Qexo是一个强大而美观的在线静态博客编辑器,它不仅限于编辑,而是将静态博客提升到新的高度。通过GPL3.0开源协议,Qexo提供了一个集编辑、管理、扩展于一体的平台,让静态博客也能拥有动态的元素。无论你是Hexo、Hugo还是Valaxy的用…

【论文阅读】<YOLOP: You Only Look Once for PanopticDriving Perception>

Abstract 全视驾驶感知系统是自动驾驶的重要组成部分。一个高精度的实时感知系统可以帮助车辆在驾驶时做出合理的决策。我们提出了一个全视驾驶感知网络(您只需寻找一次全视驾驶感知网络(YOLOP)),以同时执行交通目标检…

C++类和对象中篇

🐇 🔥博客主页: 云曦 📋系列专栏:[C] 💨路漫漫其修远兮 吾将而求索 💛 感谢大家👍点赞 😋关注📝评论 文章目录 📔前言📔1、类的六个…

源代码怎么加密防泄漏?9种方法教会你

想做源代码加密防止泄漏,首先要了解程序员可以通过哪些方式将源代码传输出去! 程序员泄密的常见方式 物理方法: — 网线直连,即把网线从墙上插头拔下来,然后和一个非受控电脑直连; — winPE启动,通过光盘…

怎么写毕业论文的? 推荐4个AI工具

写作这件事一直让我们从小学时期就开始头痛,初高中时期800字的作文让我们焦头烂额,一篇作文里用尽了口水话,拼拼凑凑才勉强完成。 大学时期以为可以轻松顺利毕业,结果毕业前的最后一道坎拦住我们的是毕业论文,这玩意不…

常用目标检测算法介绍

目录 1. 常用目标检测算法 2. R-CNN 模型 3. Fast R-CNN 模型 4. Faster R-CNN 模型 5. SSD 模型 1. 常用目标检测算法 在深度学习框架下,目标检测方法通常涉及图像定位和分类两个关键方面。有两种主要的解决方法:一种是一阶(one-stage&…

去除快捷方式的箭头图标

文章目录 取消箭头显示恢复箭头显示结果展示 添加快捷方式之后,会有箭头图标,部分场景下看着较为难受: 可以通过如下方式取消/显示箭头: 取消箭头显示 新建一个.bat文件,内部加入如下命令: reg add "…

2024北京市人工智能大模型行业应用分析报告

来源:北京市科学技术委员会 方向一为基于AIGC技术的智能审计合规研究,由北京银行提出,以 提高审计工作效率和准确性为核心目标,需要参赛企业针对检查内容, 利用大模型技术寻找并给出相关现象涉及的制度名称及相关原文…

element ui的确认提示框按钮样式修改

修改确认提示框的默认按钮样式,使用css强制修改 例: js代码: deleteUser(params){this.$confirm("您确定要删除吗?此操作无法撤销并且将永久删除所有数据。", "提示", { type: "warning", cancel…

新款锐科达SV-2402VP SIP广播音频模块18123651365支持RTP流音频广播

一、模块介绍 SV-2402VP网络音频模块是一款通用的独立SIP音频播放模块,其带2*15W功放音频输出,可以轻松地嵌入到OEM产品中。该模块对来自网络的SIP协议及RTP音频流进行解码播放。 该模块支持多种网络协议和音频解码协议,可用于VoIP和IP寻呼…

解决Tomcat日志乱码问题

1、 修改apache-tomcat-10.1.23/conf/server.xml URIEncoding"UTF-8"2、 修改apache-tomcat-10.1.23/conf/logging.properties # java.util.logging.ConsoleHandler.encoding UTF-8 java.util.logging.ConsoleHandler.encoding GBK参考 https://www.jb51.net/ar…

一键接入电商API数据接口京东API通过商品ID、URL采集商品详情页实时数据API接入指南

要一键接入京东电商API数据接口并采集商品详情页的实时数据,您需要按照以下步骤操作: 注册账号:您需要注册一个账号。完成注册后,您将获得用于API认证的ApiKey和ApiSecret。选择API:根据自己的需求选择合适的API服务。…

域控安全 ----> Ntds.dit文件抓取

大家还记得内网渗透的初衷吗??? 找到域馆,拿下域控!! 拿下了域控就是拿下了整个域!! 但是大家知道拿下域环境之后应该怎么操作吗(灵魂拷问)??? …

科研综述写作技巧:三大要领与实战应用

​在科研工作中,综述不仅是研究者对既有知识体系的梳理与整合,更是为接下来的研究提供方向与思路的重要工具。写好一篇综述,需要掌握三大要领。 要领一:明确目标与定位 在开始综述写作之前,首先要明确综述的目标与定位…

Spring 常用的注入方式有什么?

Spring 是一个非常流行的 Java 开发框架,它提供了多种依赖注入(Dependency Injection)的方式,使得开发者可以轻松地管理应用程序中的组件依赖关系。在 Spring 中,常用的注入方式主要包括构造器注入、Setter 方法注入、…

全网最全:一文入门最热的LLM应用开发框架LangChain

f#### 1. LangChain 简介 1.1. LangChain 发展史 LangChain 的作者是 Harrison Chase,最初是于 2022 年 10 月开源的一个项目,在 GitHub 上获得大量关注之后迅速转变为一家初创公司。2017 年 Harrison Chase 还在哈佛上大学,如今已是硅谷的…

【Django项目】 通过AI实现视频转文字

使用Django构建一个视频—>文字 转换器: 输入视频地址,通过OpenAI的接口分析视频,返回视频内容的文字。 视频 代码 运行此程序,需要OpenAI-key和设置Postgres数据库。 (吐槽一下,作者把这些信息都直接写…

【数据结构初阶】直接插入排序

最近浅学了直接插入排序,写个博客做笔记!笔记功能除外若能对读者老爷有所帮助最好不过了! 直接插入排序是插入排序的一种,那么介绍直接插入排序之前先介绍一下常见的排序算法! 目录 1.常见的排序算法 2.直接插入排…