八股总结(Java)持续更新!
八股总结(java)
-
ArrayList和LinkedList有什么区别
- ArrayList底层是动态数组,LinkedList底层是双向链表;
- 前者利于随机访问,后者利于头尾插入;
- 前者内存连续分配,后者通过指针连接多块不连续的内存;
-
实现多线程的几种方式
- 通过继承Tread并重写run();
- 实现无返回值的Runnable接口;
- 实现有返回值的Callable接口,通常于Future一起使用;
- 使用
ExecutorService
线程池工厂; - 使用
ThreadPoolExecutor
自定义线程池; - 使用
ComletetableFuture
异步链式编程;
-
线程池有哪些核心参数
-
核心线程数:线程池创建时就存在的线程数,并且不会因为任务运行完成而销毁;
-
最大线程数:线程池最大承载的线程数,非核心线程任务运行完成后自动销毁;
-
工作队列:用于存放待执行任务的阻塞队列,有基于数组的有界队列,基于链表的无界队列,不存储元素的队列但每个插入必须等待一个移除,支持优先级排序的无界队列,不存储元素的特殊队列;
-
线程空闲时间:非核心线程任务运行完成后等待新任务的最长时间;
-
时间单位:空闲时间的单位;
-
拒绝策略:当任务数超过最大线程数时的行为,默认抛出异常,也可以由提交任务的线程直接执行任务,也可以丢弃任务不抛出异常,也可以丢弃队列最旧任务并重新提交;
-
-
线程的状态有哪些
-
新建:线程new,但没有start();
-
可运行:调用start(),但还在操作系统分配资源;
-
阻塞:线程因为锁而阻塞;
-
等待:线程无限期等待其他线程的操作;
-
超时等待:线程等待其他线程的操作,但设置过期时间;
-
终止:线程执行完毕或异常终止;
-
-
String、StringBuilder、StringBuffer有什么区别
-
String,是定长字符串,对String的所有操作都会创建新的对象;
-
StringBuilder,可以在不创建新对象的情况下对字符串内容进行修改,线程并不安全,适用于单线程环境下;
-
StringBuffer,可以在不创建新对象的情况下对字符串内容进行修改,线程安全,适用于多线程环境下;
-
-
等于号(==)和equals方法有什么区别?
- ==常用于基本数据类型之间的比较,对于引用数据类型,则对比的是其地址
- equals常用于比较两个对象的内容是否相等,默认情况下Object类的equals方法比较的也是地址,但和许多包装类都重写了equals方法,使其比较的是对象的内容;
-
final关键字有什么作用?修饰类时有什么效果?
- final修饰的变量称为常量,如果修饰的是基本数据类型,则其值不能修改,若修饰的是引用数据类型则其指向的对象不能修改,但可以修改其对象内部状态;
- 修饰方法,不能被子类重写;
- 修饰类,不能被继承;
-
HashMap的底层原理
- 底层是一个默认长为16的动态数组,其存储链表或红黑树;
- 当有键值对存入时,键会通过哈希函数映射当数组对应下标位置,值则会存入链表中;
- 若链表长度超过8且数组长度大于等于64则转换为红黑树;若红黑树的数据量小于6,则退化为链表;
- 若数组元素数量超过默认负载因子的0.75就成倍扩容;
-
Hashmap的扩展知识
-
为什么链表长度超过8要转换为红黑树
- 在极端情况下,数据分配不均,导致大量键值对集中在一个元素链表中,会导致hashmap退化为链表影响效率;
- 根据大数据统计,链表长度超过8是因为哈希冲突导致的;
为什么选择红黑树而不是B+树
- 红黑树是自适应平衡二叉树,内存占用小,在hashmap中性能足够;
- B+树的适用情景为io数据流的读取,因为其节点可以有多个子节点,每个节点可以存储多个键,用于减少树的高度,降低磁盘io访问次数,并且所有子节点在同一层,用于平衡io的平均访问时间,叶子节点之间通过指针连接,形成一个有序链表,支持高效返回查询;
-
-
ConcurrentHashMap的底层原理
-
concurrentHashMap的底层就是HashMap的基础上保证线程安全;
-
在jdk8之前,采用分段锁实现线程安全,内部有多个段组成,每个段维护一部分数据,并各自有一把锁。修改某个段的数据时对该段加锁保证线程安全;读取则不用加锁,因为段内的数组使用volatile修饰,保证可见性;
-
jdk8后,采用CAS+synchronized实现线程安全,当要向数组中某一位置插入数据时,若该位置无数据就使用CAS进行写入,反之加锁后进行写入;
-
当数组进行扩容时采用的是并发+CAS+锁的方式,让扩容的同时不影响读取操作;
-
为什么改为CAS+锁,因为原来的分段锁每个段都需要维护一把锁,占用了过多的资源,并且段相比较节点的颗粒度较大;
-
class的生命周期
- class的生命周期指类从JVM虚拟机加载开始,直到卸载的过程,生命周期包括加载、验证、准备、解析、初始化、使用和卸载七个阶段;
- 加载,new创建类的实例、访问类的静态方法或属性、使用反射时会将class文件加载到JVM中,生成字节码class文件;
- 验证,确保字节码class文件的合法;
- 准备,静态变量分配内存并设置默认值;
- 解析,符号引用转为直接引用;
- 初始化,执行static{}代码块和静态变量的显式赋值;
- 使用;
- 卸载,释放内存;
-
JVM是什么
- java的java虚拟机,负责执行java字节码,并提供内存管理、垃圾回收等机制;
- JVM是java“一次编写,随处运行”的核心,将java源码编译为class字节码再解释或编译为机器码交由操作系统执行;
- JVM主要组成有类加载器,运行时数据区,执行引擎等;
-
JVM的工作流程
-
编写java代码;
-
使用javac编译为class字节码;
-
加载字节码;
-
执行字节码,交由JIT编译器与解释器,转换为机器码;
-
内存管理,分为堆、栈、方法区等;
-
程序结束,释放所有资源;
-
-
JVM的内存模型
- 主要分为分为堆、栈、方法区(jdk8前叫永久代)、pc程序计数器、直接内存;
- 方法区,用于存放类信息,常量池,静态变量等;
- 堆,用于存放对象实例和数组,是垃圾回收的主要区域,分为新生代和老年代;
- 栈,用于存放局部变量、方法调用帧;
- 程序计数器,用于记录当前线程执行的字节码指令位置用于线程切换后回复执行位置;
- 直接内存,手动管理,不受JVM堆内存限制;
- 垃圾回收机制
-
是JVM自动管理内存的核心机制,负责回收不再使用的对象,释放内存空间;
-
垃圾回收的基本原理是,可达性分析,从GC根对象触发,遍历所有可达对象,不可达对象视为垃圾进行回收;
-
垃圾回收算法:
- 标记-清除算法:从根对象出发,标记所有可达对象,清除未被标记的对象;缺点是会产生内存碎片;
- 标记-整理算法:在标记-清理算法的基础上,标记后先将存活的对象移动到另一片区域,之后进行清除;
- 复制算法:将内存分为AB两块,A区存活的对象赋值到B区,清理A区的所有对象;
- 分代收集:将堆分为新生代和老年代,新生代是新对象分配的区域,采用复制算法,老年代是长期存活的对象,使用标记-清除或标记-整理算法;
-
垃圾回收器:
- 单线程回收器,适用于单线程;
- 多线程回收器,适用与多线程;
- CMS回收器,采用三色标记法,并发执行,对象尚未被标记则为白色,对象已被标记但引用的对象还未标记则为灰色,对象及其引用对象都被标记则为黑色,适用于响应时间敏感的应用;工作流程是:
- 初始标记:标记从GC根对象直接可达的对象,标记灰色,需要STW停顿;
- 并发标记:标记所有灰色对象的引用对象;
- 重新标记:重新标记并发标记阶段所有修改引用或者不在引用的对象,需要SWT停顿;
- 并发清除:清除所有白色标记的对象;
- G1回收器,分区回收,适用于低延迟的大内存应用;
- ZGC回收器,超低延迟;
- G1垃圾回收器与CMS垃圾回收器的区别
-
G1是在可控的停顿时间内实现高吞吐量,并且适用于大内存。CMS尽量减少停顿时间,适用于中小内存;
-
G1堆内存管理基于分区管理,划分为多个大小相同的区域,每个区域可以是年轻代、老年代和永久代。而CMS则将堆内存划分为新生代和老年代;
-
G1内存管理采用并发标记整理算法,减少碎片,而CMS采用并发标记清除算法,容易造成FullGC堆溢出;
- 发生了OutOfMemoryError如何解决
- 首先根据报错确认问题在哪;
- 使用jmap生成堆转储文件;
- 分析堆内存;
- 根据原因调整JVM参数;
- 选择合适的垃圾回收机制;
-
CAS的原理
- CAS是一种无锁原子操作,他有三个属性,变量的内存地址,预期值,新值,如果期望值与内存中的值一致则更新为新值;
- CAS存在ABA问题,ABA问题是当一个变量从A变为B再变为A,CAS机制会误认为值没有被修改;
- 常见的解决方案是通过给变量加上时间戳或是版本号,每次修改就会更新,这样修改值时,CAS就能检测到变化;
-
volatile字段的原理,是否能替代锁
- volatile是java的修饰词,用于确保变量的可见性与有序性,主要作用于解决多线程环境下的内存可见性问题;
- 在多线程环境下,每个线程都有自己的工作内存,当线程对变量进行修改时,会先修改变量存放到自己的内存中,不会立即同步给主内存,导致其他线程不能看到最新的值;
- volatile会强制修改后的值立即写会主内存,并强制其他线程重新读取该变量,保证可见性;
- volatile会保证变量的读写操作按照代码的顺序执行;
- volatile的底层原理是依赖于内存屏障,他是一种CPU指令用于控制指令的执行顺序与内存可见性;
- 在写入变量时,会插入写屏障,确保之前操作都完成后,在将新的变量同步给主内存;
- 在插入变量时,会插入读屏障,确保之后的操作都能看到最新的值;
- volatile只能解决可见性与有序性的问题,无法解决复合操作的原子性问题;
-
双亲委派模型
- 是java类的加载机制,采用逐级委派的方式加载类,主要目的是保证java核心类的安全性和避免类的重复加载;
- 按照层次关系分为:
- 启动类加载器:负责加载Java核心类库;
- 扩展类加载器:负责加载扩展类库;
- 应用类加载器:负责加载开发者自己编写的Java代码;
- 自定义类加载器:开发者继承ClassLoader自定义类加载逻辑;
- 工作机制:当类加载器需要加载一个类时,会由当前加载 器先向父类加载器发送加载请求,直到启动类加载器,如果找不到则由当前加载器加载;
-
AQS的底层原理
- AQS(抽象队列同步器)是Java并发包中的核心组件,用于实现锁和同步器;
- AQS采用FIFO队列+CAS操作来管理锁的同步和排队,其底层主要通过状态变量(state)和队列管理来实现线程的阻塞、唤醒、等待和竞争锁等功能,通过CAS操作保证线程安全;
- state变量用于表示同步的当前状态,state==0表示锁未被占用,!=0表示已被占用;
- FIFO队列来管理等待同步的线程,当线程尝试获取同步资源失败时会被放入队列,按照先进先出的顺序等待获取同步;
- 队列数据结构是一个双向链表,每个等待的线程都是一个队列的节点,节点包含线程和前后指针;头部是等待同步的线程,尾部是最新加入的线程;
-
Executors线程工厂类有哪些常见的工厂方法
-
newFixedThreadPool(int nThreads),创建一个固定大小的线程池,核心线程数与最大线程数相同,适用于执行长期稳定任务,保证一定并发量的情况;
-
newCachedThreadPool(),创建一个可缓存的线程池,无核心线程,最大线程数为Integer.MAX_VALUE,适用于执行大量短时间任务的情况,能够充分利用系统资源;
-
newSingleThreadExecutor(),创建单线程的线程池,保证所有任务按照顺序执行;
-
-
数组如何转为list
- 使用Arrays.asList(T… a),返回定长list;
- 使用new ArrayList<>(Arrays.asList(array));
- 使用Stream,Arrays.stream(array).collect(Collectors.toList());
- 使用for循环手动添加;
-
如何遍历list
- 增强型for循环;
- 普通循环,访问下标;
- 迭代器;
- Stream流,forEach(System.out::println);
-
任务提交给线程池后是怎么工作的
- 线程池会先检查核心线程数,小于核心线程数,会创建新线程;
- 任务队列未满则任务进入阻塞队列;
- 如果任务队列(ArrayBlockingQueue)已满,且当前线程数小于最大线程数,则会创建新线程执行任务;
- 如果已经达到最大线程数,线程池会执行拒绝策略;
-
wait()和sleep()的区别
- wait和sleep方法都用于使用线程暂停执行,但他们在使用方式、功能和影响上有显著区别;
- sleep是Thread类的静态方法,可以在任何地方调用,无需持有对象锁,调用后线程会暂停执行指定的时间,但不会释放已持有的锁,其他县城无法获取这些锁;
- wait是Object类的方法,必须在同步方法或同步代码块内调用,并且在调用时需要持有该对象的监视器锁,调用后,线程会释放已持有的锁,允许其他线程获取这些锁,线程会进入等待状态,直到被其他线程调用其对象的notify()方法唤醒。如果wait添加了过期时间,若未超过过期时间也可以被notify唤醒,超过时间后自动唤醒;
- sleep常用于让线程暂停执行一段固定的时间,例如实现定时任务或控制线程执行频率;wait常用于线程间的通信;
-
并行与并发的区别:
- 并行(Parallelism): 多个任务在同一时刻同时执行,通常需要多核处理器的支持。
- 并发(Concurrency): 多个任务在同一时间段内交替执行,但不一定同时执行。
-
Java常见的设计模式
- 单例模式:
- 在系统中一个类只存在一个实例,类自身负责创建并维护唯一实例,并提供一个全局方法,允许外部访问该实例;
- 常用于资源管理、配置管理和日志记录;
- 实现单例模式一般通过双重检查锁定,在需要时才创建实例,并通过双重检查和同步块确保线程安全,同时提高性能;
- 普通工厂模式:
- 由一个工厂类根据传入的不同参数创建不同的产品实例,将对象创建逻辑封装在工厂类中;
- 将对象的创建与使用分离,降低了耦合性;
- 缺点是集中力所有对象的创建逻辑,违反了单一职责原则,可能导致工厂类过于复杂。且当需要添加新产品时,需要修改工厂类的代码,不符合开闭原则;
- 工厂方法模式:
- 定义了一个创建对象的接口,由子类决定实例化哪个具体类;
- 相比较普通工厂方法,符合开闭原则,增加新产品时无需修改现有代码;
- 符合单一职责原则,每个具体工厂类只负责创建对应的产品;
- 增加了系统的复杂度,需要对每个具体实现创建工厂类;
- 抽象工厂方法:
- 提供一个创建一系列相关或相互依赖对象的接口,也就是对多组产品抽象其方法,封装隐藏其产品创建的过程;
- 单例模式:
-
threadLocal是什么?
- TreadLocal是一个创建线程局部变量的类,通常情况下,多个线程共享同一变量,可能导致并发问题,使用TreadLocal,存储的变量只能由当前线程使用,保证线程隔离;
- 使用TreadLocal时,可能会导致内存泄露,因为与线程生命周期绑定,如果不及时清理,可能会导致无法回收对象占用内存,所以需要在不需要TreadLocal时调用remove()清理;
-
java的线程池,如果是8核的服务器,如何设置你的核心线程数
- 通常情况下可以将核心线程数设置为CPU核心数,因为每个核心可以独立执行一个线程,从而提高并发性能;
- 若任务是高I/O密集型任务,任务需要主动等待I/O操作,可以设置更多的核心线程,因为线程在等待I/O时,可以释放CPU资源给其他线程,可以考虑将核心线程数设置为CPU核心数的2到4倍;
- 若任务是计算密集型的,核心线程数一般设置为和CPU核心数相同或略低,因为设置过多线程可能导致上下文切换开销过高,从而影响性能;
-
BIO、NIO、AIO
- BIO、NIO、AIO是Java用于处理输入输出I/O操作的三种主要方式,有不同的特点与适用场景;
- BIO通常用于处理网络通信和文件操作,当前线程会阻塞,直到I/O操作完成;特别是在高并发的情况下。BIO会面临线程的创建和销毁的开销,会导致性能瓶颈,但对并发量不高或资源有限的系统,BIO仍然是一个简单且有效的操作;
- NIO采用非阻塞操作,通过单个线程专门负责处理多个I/O操作。让线程在等待数据时可以继续执行其他任务。NIO中核心组件有选择器Select、通道channel和缓冲区buffer:
- buffer是存储数据的容器,所有数据的读写操作都必须通过buffer完成;
- channel是数据通道,与请求IO数据流的设备进行数据读写,本身也是双向的,可读可取;
- select管理多个channel,能够同时监听多个channel上的事件,当有线程发生I/O操作时,会通知该线程进行相应的处理;
- AIO是一种异步操作,所有的I/O操作会在后台自动分配合适的线程执行,主线程不会阻塞等待,可通过回调机制获知操作完成;
- BIO每个请求一个线程,对高并发支持差,线程资源消耗大,适用于小型应用;NIO通过非阻塞I/O和事件驱动机制提供了较高的性能但实现相对复杂,适用于高并发应用;AIO采用完全异步的操作,适用于需要处理大量I/O操作的高并发、低延迟应用;
-
同步和阻塞这两个概念?
- 同步和阻塞是在并发编程中经常出现的概念,同步是指对共享数据的访问控制,多个线程可能同时访问共享资源,如果没有合适的同步机制,可能出现数据竞争或数据不一致,通常采用synchronized或reentrantlock等保证同一时刻只能有一个线程执行某一方法或代码块;
- 阻塞是指在线程执行过程中等待某些条件满足,才能继续执行的操作,常见的阻塞操作有I/O操作和线程间的同步操作,例如文件的读取和网络请求的操作,线程会一直等待数据准备好或请求完成。还有线程在等待某个锁时,如果该锁被其他线程占用,当前线程会被阻塞,直到锁释放为止;
-
synchronized和reentranklock的底层原理
- synchronized是一种内置锁,用于控制对共享资源的访问,保证了同一时刻只有一个线程能够访问被同步的代码块或方法,不支持公平锁,只根据操作系统的调度。其底层通过对象监视器和内存屏障来实现;
- 对象监视器,每个对象在JVM层面上都有一个与之关联的监视器锁,当线程访问一个sunchronized方法或代码块时,必须先获得该对象的监视器锁,确保同一时刻只有一个线程能获取到该锁,其他线程想执行相同的方法或代码快,会被阻塞,知道该线程释放锁;
- 内存屏障,对共享变量的修改对其他线程是立即可见的,在每次进入或退出synchronized方法或代码块时,使用内存屏障;
- reentrantlock是java的一种显式重入锁,由开发者决定lock()上锁与unlock()释放锁的过程,提供了比synchronized更细颗粒度的控制,一个线程可以多次获取该锁而不会导致死锁,有公平锁与非公平锁。在执行过程中允许通过lockInterruptibly()中断运行,并抛出InterruptedException异常,底层是基于AQS来实现的。
- AQS,通过一个FIFO队列来管理请求锁的线程,每个线程尝试获取锁时,如果获取不到,线程会进入队列等待。并使用CAS操作尝试获取互斥锁,线程会不断尝试获取锁,直到成功,如果线程已经持有锁,可以多次获取,不会发生死锁;
- synchronized是一种内置锁,用于控制对共享资源的访问,保证了同一时刻只有一个线程能够访问被同步的代码块或方法,不支持公平锁,只根据操作系统的调度。其底层通过对象监视器和内存屏障来实现;
-
有哪些垃圾回收机制
- 标记-清除算法:首先标记出所有需要回收的对象,然后统一清除这些被标记的对象,缺点是可能产生大量不连续的内存碎片,影响内存分配;
- 标记-整理算法:首先标记出所有需要回收的对象,然后将所有存活的对象向内存一端移动,最后清理边界以外的内存,可以避免内存碎片,适合短生命周期对象(如新生代),但会造成内存利用率低;
- 分代收集算法:根据对象生命周期将堆分为新生代和老年代,新生代采用复制算法,老年代采用标记-清除或标记-整理算法,能够针对不同代优化回收效率
- 三色标记算法:通过白、灰、黑三色标记对象状态,支持并发标记;
-
Java的基本数据类型
- 整型:
- byte: 大小1字节;
- short:大小2字节;
- int:大小4字节;
- long:大小8字节;
- 浮点类型:
- float:大小4字节;
- double:大小8字节;
- 字符类型:char,大小2字节;
- 布尔类型:boolean,1字节;
- 整型:
-
Integer 缓存池的区间
-
Integer缓存池是一种优化机制,用于缓存一定范围内的Integer对象,避免频繁创建和销毁对象,从而提高性能;
-
Integer缓存池默认范围是-128-127,当通过Integer.valueOf()或者自动装箱创建Integer对象时,如果值在此返回,JVM会直接从缓存池中返回已存在的对象,而不是新建对象;
Integer a = 127; // 自动装箱,使用缓存Integer b = 127; // 复用缓存System.out.println(a == b); // true(同一对象)Integer c = 128; // 超出缓存范围,新建对象Integer d = 128; // 新建另一个对象System.out.println(c == d); // false(不同对象)
可以通过JVM参数-XX:AutoBoxCacheMax=修改缓存上限;
-
其他包装类,如Byte、Short、Long缓存区间为-128-127,不可调整;
-
-
java重载和重写的区别
- 重载是指,在同一个类中,允许存在多个同名方法,但他们的参数不相同。提供同一功能的多种实现方式,在多态特性中,指编译时多态;
- 重写是指,在子类中重新定义父类的同名方法,要求方法名称、参数与返回类型完全相同,在多态特性中,指运行时多态;
- 不能根据返回值区分重载,因为重载仅依赖于参数;
- static方法不能被重写,因为属于类级别的,但子类可以定义同名static方法,属于隐藏;
-
介绍一下常见的集合类
- List:ArrayList,LinkedList,vector;
- Set:hashSet,LinkedHashSet,TreeSet;
- Map:HashMap,LinkedHashMap,ConcurrentHashMap,TreeMap,HashTable;
- queue:PriorityQueue,ArrayDeque,ConcurrentLinkedQueue;
-
Hashtable是线程安全的吗?
- HashTable是线程安全的,在所有的方法上添加了synchronized关键字实现线程安全;
- 保证同一时间只能有一个线程执行该实例的任何方法,不同的线程操作会被串行化;
- 会导致并发度低,其复合操作非原子性;
-
java new一个对象过程是什么?
- 首先,若该对象没有被加载会交由JVM类加载器进行加载;
- 再为其在堆上分配内存空间;
- 对其进行实例化;
- 对字段设置默认值或注入依赖;
- 初始化;
- 返回对象引用地址;
-
面向对象OOM的三大特性
- 封装:将对象的方法与属性抽象出来封装在一个类中,使用访问控制对外隐藏内部实现细节;
- 继承:子类继承父类的属性和方法,实现代码复用和扩展;
- 多态:同一操作在不同对象中可以有不同的行为,包括编译时多态(重写)和运行时多态(重载);
-
接口和抽象
- 接口,是一种完全抽象的类型,仅定义方法的签名,不提供具体实现,所有方法默认是public abstract,所有字段默认是public static final,实现此接口必须遵守其定义的所有方法;
- 抽象,是一种部分抽象的类,可以包含抽象方法和具体方法,用于代码复用,可以使用构造方法用于初始化,可以包含非final的成员变量,一个类只能继承一个抽象类,子类必须实现其抽象方法;
-
List与Set的区别
- List允许元素重复,set不允许重复;
- List可以使用索引进行访问,Set不支持;
-
hashset的底层原理
- HashSet是用HashMap实现的,将所有的元素作为key存入,value中是一个统一的虚拟值;
- 先将元素通过hash函数定位到指定下标,如果该位置有元素,使用equals判断两个值是否相同,所以必须对存入的元素类其equals与hashcode方法进行重写,定义其相同的逻辑,不然如果元素数据相同,但其引用不同也会插入重复元素;
-
如何获取反射
- 使用类名.class,使用对象的.getClass(),通过全限定类名Class.forName(“com.example.MyClass”)获取;
-
进程,线程,协程的区别
- 进程是系统分配资源的最小单位,拥有独立的运行空间,一个进程的崩溃不会影响其他进程,进程创建、切换和销毁需要销号较多的系统资源,进程之间通信复杂,因为进程之间是相互独立的,一般通过共享内存或系统提供的消息队列进行通信;
- 线程是进程的执行单元,CPU调度的最小单位,使用进程的内存空间,一个进程的线程之间可以直接访问共享数据;线程的切换会先保存当前线程上下文,之后从线程就绪队列中选择目标队列,恢复其上下文,执行切换;
- 协程是go语言进行并发操作的一种方式,由用户代码进行调度;
-
进程的上下文开销为什么会比线程大?
- 每个进程都有独立的虚拟地址空间,切换时需要切换页表或内存映射等,导致CPU缓存失效,同一进程的线程共享内存空间,仅需要切换私有数据;
- 进程切换必须进入内核态,由操作系统调度器完成完整上下文保存与加载,而用户态进程切换完全在用户空间完成,内核态线程需进入内核态但资源操作更少;
-
引用数据类型和基本数据类型有什么区别?
- 引用数据类型存储在堆内存中,基本数据类型存储在栈内存中;
- 基本数据类型存储数据值,引用数据类型存储对象的引用地址;
- 引用数据类型有:类、接口、枚举、字符串、数组;
-
实现深拷贝和浅拷贝的方式?
-
浅拷贝:只复制对象本身和其基本类型字段,对于引用类型字段,只复制引用不复制引用对象,一般使用对象的clone()方法;
-
深拷贝:创建新的对象,不仅复制其对象值,还复制其引用指向的对象,可以重写clone()手动递归克隆所有对象,也可以使用序列化;
-
-
哪些对象可以被视为GC Root?
- 对象通过可达性分析判断是否为垃圾,从GCRoot出发,遍历所有的对象,无法访问到的对象就是垃圾;
- 栈帧中到局部变量、参数、类的静态字段、常量、系统类加载器加载的类、线程自身的引用等可以视为GCRoot;
相关文章:
八股总结(Java)持续更新!
八股总结(java) ArrayList和LinkedList有什么区别 ArrayList底层是动态数组,LinkedList底层是双向链表;前者利于随机访问,后者利于头尾插入;前者内存连续分配,后者通过指针连接多块不连续的内存…...
SpringBoot3快速入门笔记
springboot3简介 SpringBoot 帮我们简单、快速地创建一个独立的、生产级别的 Spring 应用(说明:SpringBoot底层是Spring) 大多数 SpringBoot 应用只需要编写少量配置即可快速整合 Spring 平台以及第三方技术 特性: ● 快速创建…...
vue3中,element-plus中el-input的v-model和value的用法示例
el-input的v-model,邦定响应式变量 <el-col :span"6"><el-form-item label"检验类别" prop"verifyType"><el-input v-model"applyAllInfo.applyBasicInfo.verifyTypeName" readonly /></el-form-item…...
python求π近似值
【问题描述】用公式π/4≈1-1/31/5-1/7..1/(2*N-1).求圆周率PI的近似值。 从键盘输入一个整数N值,利用上述公式计算出π的近似值,然后输出π值,保留小数后8位。 【样例输入】1000 【样例输出】3.14059265 def countpi(N):p0040nowid0for i i…...
Gerapy二次开发:搜索器组件设计开发与应用(Vue父子组件通信)
搜索器组件设计开发与应用 写在前面搜索器字段定义与样式设计具体实现components/Search.vuedeploy/Index.vue后端views.py运行效果总结欢迎加入Gerapy二次开发教程专栏! 本专栏专为新手开发者精心策划了一系列内容,旨在引领你深入探索Gerapy框架的二次迭代之旅。 本专栏将全…...
深入解析Python爬虫技术:从基础到实战的功能工具开发指南
一、引言:Python 爬虫技术的核心价值 在数据驱动的时代,网络爬虫作为获取公开数据的重要工具,正发挥着越来越关键的作用。Python 凭借其简洁的语法、丰富的生态工具以及强大的扩展性,成为爬虫开发的首选语言。根据 Stack Overflow 2024 年开发者调查,68% 的专业爬虫开发者…...
Python爬虫-爬取全球股市涨跌幅和涨跌额数据
前言 本文是该专栏的第52篇,后面会持续分享python爬虫干货知识,记得关注。 本文中,笔者将基于Python爬虫,实现批量采集全球股市行情(亚洲,美洲,欧非,其他等)的各股市“涨跌幅”以及“涨跌额”数据。 具体实现思路和详细逻辑,笔者将在正文结合完整代码进行详细介绍。…...
【NLP 59、大模型应用 —— BPE 算法】
你和生生不息的河流,生动了我人生中的美好瞬间 —— 25.4.11 一、词表的构造问题 为了nlp模型训练,词表(字表)是必要的 统计训练语料中的所有字符(或词)是一种做法,但是容易出现一些问题&…...
SQL基础入门:从CRUD到JOIN再到索引(通俗易懂版)
一、为什么需要SQL? 想象你在管理一个图书馆: 传统方法:手动记录每本书的位置、借阅者、归还日期SQL方法:用数据库系统自动管理,快速查询《Java编程思想》在哪个书架 SQL(Structured Query Language&…...
系统编程1(进程的概念与原理)
进程的概念与原理 计算机组成部分一般遵循冯诺依曼结构,也就是由控制器、运算器、存储器、输入设备、输出设备五个部分组成。 ⦁ 程序的编译 一般在编写出程序之后,并不能直接运行,而是需要把程序通过编译器进行编译,生成可执行…...
Git基础知识
Git基础知识 目录 一、Git简介 1.1 什么是Git?1.2 基本概念1.3 Git与其他版本控制系统的区别 二、Git安装与配置 2.1 安装Git2.2 基础配置2.3 高级配置2.4 多账户配置 三、基本操作 3.1 创建仓库3.2 基本工作流3.3 分支操作3.4 查看历史 四、高级操作 4.1 撤销修改…...
【Flink运行时架构】核心组件
在Flink的运行架构中,有两大比较重要的组件:作业管理器(JobManager)和任务管理器(TaskManager)。 Flink的作业提交与任务处理时的系统如下图所示。 其中,客户端并不是处理系统的一部分ÿ…...
【区块链安全 | 第四十篇】合约审计之delegatecall(二)
文章目录 漏洞代码代码分析攻击流程攻击代码前文重现修复建议审计思路 在阅读本文之前,请确保已先行阅读:【区块链安全 | 第三十九篇】合约审计之delegatecall(一) 漏洞代码 存在一漏洞代码如下: // 库合约…...
Redis实现分布式定时任务
设计思路 任务表示:每个任务通过一个特定格式的键来表示。键名可以包含任务ID等信息,值可以是任务的具体内容或指向任务详情的引用。过期机制:利用Redis的EXPIRE命令为任务设置过期时间,当到达设定的时间点时,Redis会…...
ERC20合约的基本调用
文章目录 ERC20合约的基本调用合约功能compile.js 代码读取文件 进行合约编译获取二进制对象导出对象 index.js 代码编译合约读取私钥设置收款账户构造 web3 对象获取账户地址获取 abi 和 bin创建合约交易部署合约构造转账交易验证转账后余额 测试项目目录执行查询 ERC20合约的…...
『Kubernetes(K8S) 入门进阶实战』实战入门 - Pod 详解
『Kubernetes(K8S) 入门进阶实战』实战入门 - Pod 详解 Pod 结构 每个 Pod 中都可以包含一个或者多个容器,这些容器可以分为两类 用户程序所在的容器,数量可多可少Pause 容器,这是每个 Pod 都会有的一个根容器,它的作用有两个 可…...
【React框架】什么是 Vite?如何使用vite自动生成react的目录?
什么是 Vite? Vite 是一个基于原生 ES Modules 开发的前端构建工具,由 Evan You(Vue 的作者)开发。它最大的特点包括: 极速冷启动:因为利用了浏览器原生的 ES Modules,所以在开发时无需等待整…...
JS实现文件点击或者拖拽上传
B站看到了渡一大师课的切片,自己实现了一下,做下记录 效果展示 分为上传前、上传中和上传后 实现 分为两步 界面交互网络请求 源码如下 upload.html <!DOCTYPE html> <html lang"zh-CN"><head><meta charset&q…...
【Vue #3】指令补充样式绑定
一、指令修饰符 Vue 的指令修饰符(Directive Modifiers)是 Vue 模板语法中的重要特性,它们以半角句号 . 开头,用于对指令的绑定行为进行特殊处理 修饰符作用如下: 简化事件处理(如阻止默认行为、停止冒泡…...
Vue.js组件安全工程化演进:从防御体系构建到安全性能融合
——百万级流量场景下的安全组件架构与源码级解决方案 文章目录 总起:安全工程化的组件革命 分论: 一、现存组件架构的七宗罪与安全改造路径 1.1 组件生态安全赤字现状 1.2 架构级安全缺陷深度剖析 1.3 性能与安全的死亡螺旋 二、百万级…...
LINUX基础 [二] - Linux常见指令
目录 💻前言 💻指令 🎮ls指令 🎮pwd指令 🎮whoami指令 🎮cd指令 🎮clear指令 🎮touch指令 🎮mkdir指令 🎮rmdir指令 🎮rm指令 &#…...
Linux进阶命令
目录 一、touch 1. 基本语法 2. 常用选项 二、which 1. 基本语法 2. 主要功能 3. 常用选项 三、find 1. 基本语法 2. 常用选项和表达式 四、more 1. 基本语法 2. 常用操作 3. 对比 more 和 less 五、grep 1. 基本语法 2. 常用选项 六、wc 1. 基本语法 2. 常…...
【Spring Boot 过滤器】
文章目录 前言一、什么是过滤器 Filter?二、Spring Boot 中使用 Filter 的方式1. 使用 Component 注解2. 使用 FilterRegistrationBean 显式注册 三、自定义过滤器示例1. 引入必要依赖2. 创建一个自定义 Filter3. 使用 FilterRegistrationBean 显式注册 四、多个 Fi…...
SPI通讯的软硬件NSS SSM SSI
学习自记: 1. NSS(Slave Select,从设备选择) 功能: NSS是SPI通信中用于选择从设备的信号线。主设备通过拉低NSS信号选中某个从设备,使其参与通信。通信结束后,主设备释放NSS&#…...
Java基础:集合List、Map、Set(超详细版)
集合体系概述 Collection常用方法 补充:addAll() Collection的遍历方式 迭代器 增强for(空集合可以,null不可以) lambda 集合对象存储对象原理 遍历方式的区别 List集合 特点、特有方法 遍历方式 (同上)…...
vue+leaflet 区域划分_反向遮罩层
leaflet 区域划分_遮罩层 geojson在线生成器网址:(https://datav.aliyun.com/portal/school/atlas/area_selector) 点击前往阿里云geojson生成器 效果图: 实现下面效果,只需要把addSateLayer函数的调用取消掉就好了. //添加遮罩层代码function addMask() {var latlngs;var fe…...
聊一聊原子操作和弱内存序
1、原子操作概念 在并发编程中,原子操作(Atomic Operation)是实现线程安全的基础机制之一。从宏观上看,原子操作是“不可中断”的单元,但若深入微观层面,其本质是由底层处理器提供的一组特殊指令来保证其原…...
免费送源码:Java+ssm+MySQL 校园二手书销售平台设计与实现 计算机毕业设计原创定制
摘 要 信息化社会内需要与之针对性的信息获取途径,但是途径的扩展基本上为人们所努力的方向,由于站在的角度存在偏差,人们经常能够获得不同类型信息,这也是技术最为难以攻克的课题。针对校园二手书销售平台等问题,对校…...
DAPP实战篇:使用ethersjs连接智能合约并输入地址查询该地址余额
本系列目录 专栏:区块链入门到放弃查看目录-CSDN博客文章浏览阅读400次。为了方便查看将本专栏的所有内容列出目录,按照顺序查看即可。后续也会在此规划一下后续内容,因此如果遇到不能点击的,代表还没有更新。声明:文中所出观点大多数源于笔者多年开发经验所总结,如果你…...
14.【.NET 8 实战--孢子记账--从单体到微服务--转向微服务】--微服务基础工具与技术--CAP
CAP 是一款专为 .NET 生态设计的开源框架,其核心目标是解决微服务中跨服务数据一致性问题。在分布式系统中,传统事务无法跨服务保证数据一致性,CAP 通过本地事务与消息记录绑定,再利用消息中间件(如 RabbitMQ、Kafka 等…...
智能资源管理机制-重传机制
一、发送端资源管理的核心机制 1. 滑动窗口(Sliding Window) 这是TCP协议的核心优化设计: 窗口动态滑动:发送端不需要保留所有已发送的分组,只需维护一个"发送窗口"窗口大小:由接收方通告的接…...
【Linux网络与网络编程】08.传输层协议 UDP
传输层协议负责将数据从发送端传输到接收端。 一、再谈端口号 端口号标识了一个主机上进行通信的不同的应用程序。在 TCP/IP 协议中,用 "源IP","源端口号","目的 IP","目的端口号"&…...
局域网下ESP32-S3 LED灯的UDP控制
在局域网下通过IP地址控制ESP32-S3上的LED,可以使用UDP或TCP协议。以下是一个基于UDP协议的完整示例,包括ESP32-S3的服务器代码和一个简单的Python客户端代码。 ESP32-S3 服务器代码 import socket import time import network import machineled Non…...
call、bind、apply
call、bind、apply它们三个都是函数的方法,都可以用于改变this的指向问题。 var person "liangxiao" let obj {name:"张三",say:function() {console.log(this.name);} }obj.say(); setTimeout(function() {obj.say(); },1000) obj.say()打…...
Redis 哨兵模式 搭建
1 . 哨兵模式拓扑 与 简介 本文介绍如何搭建 单主双从 多哨兵模式的搭建 哨兵有12个作用 。通过发送命令,让Redis服务器返回监控其运行状态,包括主服务器和从服务器。 当哨兵监测到master宕机,会自动将slave切换成master,然后通过…...
客户端负载均衡与服务器端负载均衡详解
客户端负载均衡与服务器端负载均衡详解 1. 客户端负载均衡(Client-Side Load Balancing) 核心概念 定义:负载均衡逻辑在客户端实现,客户端主动选择目标服务实例。典型场景:微服务内部调用(如Spring Cloud…...
Ningx负载均衡
Ningx负载均衡 upstream(上游)配置负载均衡1、weight(加权轮询)2、ip_hash(负载均衡)3、url hash负载均衡4、least_conn(最小连接负载均衡) upstream(上游)配置负载均衡 Nginx负载均衡 参考: nginx从安装…...
头歌软件工程导论UML画图题(基于starUML)
一.结构化分析方法-数据流图 本关卡需要画图的一共有5关,直接将此图画好每关提交一次即可,以下的所有图均以此方法提交 二.面向对象分析之用例图 三.面向对象分析之类图 注意此处创建Class之后,双击Class出现以下选项 点击相应的选项创建属性…...
智能车摄像头开源—9 动态权、模糊PID、速度决策、路径优化
目录 一、前言 二、动态权 1.概述 2.偏差值加动态权 三、模糊PID 四、速度决策 1.曲率计算 2.速度拟合 3.速度控制 五、路径 六、国赛视频 一、前言 在前中期通过识别直道、弯道等元素可进行加减速操作实现速度的控制,可进一步缩减一圈的运行速度ÿ…...
java基础 this和super的介绍
this和super this关键字的用法super关键字的用法this与super的区别和注意事项 this关键字的用法 this是自身的一个对象,代表对象本身,可以理解为:指向对象本身的一个指针 class Person{private String name;private int age;public String …...
《Python星球日记》第25天:Pandas 数据分析
名人说:路漫漫其修远兮,吾将上下而求索。—— 屈原《离骚》 创作者:Code_流苏(CSDN)(一个喜欢古诗词和编程的Coder😊) 订阅专栏:《Python星球日记》 目录 一、引言二、数据分组与聚合1. 分组操…...
C++在Linux上生成动态库并调用接口测试
加减乘除demo代码 项目结构 CPP/ ├── calculator.cpp ├── calculator.h ├── main.cpp 头文件 #ifndef CALCULATOR_H #define CALCULATOR_H#ifdef __cplusplus extern "C" {#endifdouble add(double a, double b);double subtract(double a, double b…...
Cesium.js(6):Cesium相机系统
Camera表示观察场景的视角。通过操作摄像机,可以控制视图的位置、方向和角度。 帮助文档:Camera - Cesium Documentation 1 setView setView 方法允许你指定相机的目标位置和姿态。你可以通过 Cartesian3 对象来指定目标位置,并通过 orien…...
机器学习中的数学(PartⅡ)——线性代数:概述
首先引入代数和线性代数的概念: 在将一些直观的、基于经验或直觉的概念转化为严格的数学或逻辑定义时,一种常用方法是构建一组对象和一组操作这些对象的规则,这就是代数。线性代数是研究向量和某些操作向量的规则。 其次从更广泛的意义上定…...
基于双闭环PID控制器的永磁同步电机控制系统匝间故障Simulink仿真
欢迎微♥关注“电击小子程高兴的MATLAB小屋”获取巨额优惠 1.模型简介 本仿真模型基于MATLAB/Simulink(版本MATLAB 2013Rb)软件。建议采用matlab2013 Rb及以上版本打开。(若需要其他版本可联系代为转换,高于该版本的matlab均可正…...
在51单片机上实现平滑呼吸灯:50us定时器PWM实战指南
在51单片机上实现平滑呼吸灯:50us定时器PWM实战指南 引言 本文将详细介绍如何在51单片机平台上,通过精确的50us定时器中断实现无闪烁的呼吸灯效果。相比常见的125us实现方案,50us定时器能提供更高的PWM频率和更细腻的亮度控制。 硬件设计 基本电路配置 主控芯片:SC92F8…...
asm汇编源代码之CPU型号检测
提供1个子程序: 1. CPU型号检测 CPUTYPE 无输入参数,返回值AX指示CPU类型(报歉,当时最新CPU型号只有80486) 函数的返回值详细描述如下 CPUTYPE PROC FAR ;OUT: AX01, 8086; AX02, 80286; AX03, 80386; AX04, 80486 UP; ; more source code at http://www.ahj…...
提高课:数据结构之树状数组
1,楼兰图腾 #include<iostream> #include<cstring> #include<cstdio> #include<algorithm>using namespace std;typedef long long LL;const int N 200010;int n; int a[N]; int tr[N]; int Greater[N], lower[N];int lowbit(int x) {ret…...
python可变对象与不可变对象
文章目录 Python 中的可变对象与不可变对象不可变对象(Immutable Objects)可变对象(Mutable Objects)重要区别 Python 中的可变对象与不可变对象 在 Python 中,对象可以分为可变对象(mutable)和不可变对象(immutable),这是 Python 中非常重要的概念&…...
C++学习之金融类安全传输平台项目git
目录 1.知识点概述 2.版本控制工具作用 3.git和SVN 4.git介绍 5.git安装 6.工作区 暂存区 版本库概念 7.本地文件添加到暂存区和提交到版本库 8.文件的修改和还原 9.查看提交的历史版本信息 10.版本差异比较 11.删除文件 12.本地版本管理设置忽略目录 13.远程git仓…...