2023-04-15_面试题复盘笔记(83)

一、美团骑行后端春招一二三面面经

一面:

1. 拷打项目

2. 你会如何学习java?

1.阅读Java编程书籍和教程:有很多书籍和教程可供学习Java。您可以从初学者到专家阅读不同级别的书籍。
2.参加Java编程课程:有许多机构和学校提供Java编程课程。这些课程有助于您学习Java并获得实践经验。
3.编写Java程序:编写自己的程序是学习Java的最好方法。练习编写简单的程序,并在逐步学习的过程中尝试编写更复杂的程序。
4.加入Java社区:加入Java社区,与其他Java开发人员交流和分享经验,这有助于您扩展知识和学习经验

3. 进程和线程的区别

进程是一个正在执行的程序,它拥有自己的内存空间和系统资源,是操作系统进行资源分配和调度的基本单位。而线程是程序或进程执行的最小单位,它共享同一个内存空间和系统资源,可以看做是进程中的一个执行单元。相比进程,线程更轻量级,创建、销毁、切换的开销更小,能够更高效地利用系统资源。此外,多个线程可以并发执行,从而提高程序的并发性和响应速度。

4. 进程如何通信

进程之间可以使用不同的通信机制进行通信,包括管道、命名管道、消息队列、信号量、共享内存、套接字等。其中,管道和命名管道可以实现单向通信,消息队列、信号量和共享内存可以实现双向通信,套接字可以实现跨网络的通信。例如,管道通信可以使用pipe()系统调用来创建管道,再使用read()和write()函数进行读写操作;而共享内存通信可以使用shmget()和shmat()等系统调用来获得共享内存区域的地址,再使用指针进行读写操作。不同的通信方式有各自的优缺点和适用场景,需要根据实际需求来选择。

5. 进程之间的消息

6. 从输入baidu.com到得到网页的全过程?

从输入baidu.com到得到网页的全过程,一般包括以下几个步骤:
1.首先,当你在浏览器中输入baidu.com时,浏览器会向DNS服务器(域名系统)发起请求,查询baidu.com所对应的IP地址。
2.一旦DNS服务器返回了baidu.com的IP地址,浏览器就会向该IP地址对应的服务器发起HTTP(或HTTPS)请求。
3.服务器接收到浏览器发送的请求后,会进行一系列的处理(如验证用户身份、查询数据等),最终生成HTML文件并回传给浏览器。
4.浏览器接收到服务器返回的HTML文件后,会进行解析和渲染,将页面内容呈现给用户。
总的来说,从输入baidu.com到得到网页的整个过程涉及到多个环节和协议的交互,其中包括DNS解析、HTTP请求、服务器处理、HTML解析和渲染等

7. TCP和UDP区别

TCP和UDP都是传输层协议,但是TCP是面向连接的可靠传输协议,而UDP是面向无连接的不可靠传输协议。使用TCP进行通信时,需要先建立连接,然后再传输数据,TCP会保证数据传输的可靠性和有序性,并且会对丢失的数据进行重新传输,但是会带来一定的延时。而使用UDP进行通信时,不需要建立连接,可以直接发送数据,但是由于UDP是不可靠的,数据传输的有序性和完整性不能得到保证,所以需要在应用层添加额外的措施来保证数据的正确性。

8. TCP为什么可靠?

TCP是一种传输层协议,它使用了多种技术来确保可靠的传输。首先,TCP通过序号和确认号机制,确保数据在传输时不会丢失。其次,在传输数据之前,TCP会建立连接,并在连接建立后进行握手,以确保通信双方都同意传输数据。此外,TCP还通过重传机制、拥塞控制和流量控制等技术,进一步提高了数据传输的可靠性。因此,TCP被认为是一种可靠的传输协议。

9. TCP有什么缺点吗?

TCP协议虽然在可靠性和稳定性方面表现良好,但也有一些缺点:
1.面向连接:TCP一旦建立连接,就需要在整个通信过程中维护这个连接,包括序列号和确认序列号等信息,因此不能很好地处理短连接和大量连接的情况,这会占用大量服务器资源。
2.复杂性:TCP协议通信的过程相对较复杂,需要进行三次握手、四次挥手等操作,同时也需要处理网络拥塞、错误恢复等问题,增加了协议栈的复杂度。
3.低效性:TCP协议在传输数据时,需要进行重传、拥塞控制等操作,会降低传输效率,特别是在高延迟网络或者带宽受限的情况下。
4.不适用于实时性要求高的应用:由于TCP协议需要进行确认和重传等操作,因此在实时性要求高的应用场景下数据传输延迟会比较大。
5.拥塞控制:在网络出现拥塞的情况下,TCP会调整发送数据的速率,这会导致带宽利用率的下降,同时也会对应用性能造成影响。

10. MySQL有什么索引

MySQL中的索引是用来优化数据库查询性能的,常见的索引类型包括:
1.主键索引:唯一标识一条记录的索引,一张表只能有一个主键索引。
2.唯一索引:唯一标识一组记录的索引,可以保证表中该列的值不重复。
3.普通索引:最基本的索引,只是对列进行了索引,可以加快查询该列的速度。
4.全文索引:针对文本类型的列进行索引,快速查询关键词在文本中的出现情况。
5.外键索引:用于指定一个表的参照完整性约束的索引。
使用索引可以大大提高数据库的查询性能,但是过多的索引也会影响插入和更新操作的性能,需要权衡利弊来选择合适的索引。

11. 多列索引,哪几个有效索引

多列索引中,有效的索引取决于查询语句中涉及的列和表的结构。一般来说,当查询使用到索引的第一个列时,该索引才会被使用。因此,在一个多列索引中,最重要的列放在最左边,次要的列放在右边。如果查询涉及到了多个列,而它们并不是索引的前缀,那么这个索引就没有被使用的可能性。因此,你需要根据具体的查询语句和表结构来确定哪几个列是有效的索引列。

12. MVCC是什么

MVCC(多版本并发控制)是一种在数据库中处理并发事务的方法。它通过每个事务看到数据库的不同版本来实现数据一致性和并发控制。具体地说,MVCC通过保存每个事务开始时数据库的快照来提供多个版本,并使用一个版本控制号或时间戳来跟踪每个版本。这使得多个事务可以同时读取和写入数据库,而不需要对彼此进行严格的同步,从而提高了并发性和可扩展性。在Java中,MVCC通常用于与关系数据库交互时保证事务的一致性和隔离性。

13. Redis是什么

Redis是一个开源的、高效的、键值存储数据库。它支持多种数据结构,如字符串、哈希、列表、集合、有序集合等,可以作为数据库、缓存和消息代理等使用。它特别适合用于需要快速读写、排序、分析大量数据的场景

14. Redis宕机了?

Redis宕机可能有多种原因,比如系统故障、网络问题、磁盘空间不足、内存溢出等等。在应对Redis宕机问题时,我们可以采取以下措施:
1.立即查看Redis日志文件,查找可能的故障原因。
2.重启Redis服务,如果无法重启,则考虑升级Redis版本,或者重新安装Redis。
3.检查服务器及网络情况,查看是否有异常占用了Redis的资源。
4.调整配置文件,根据实际情况增加或减少Redis的内存使用量。
5.监控Redis的运行状态,预防Redis宕机的发生,比如使用Redis Sentinel或Redis Cluster等高可用方案。
总的来说,要想有效解决Redis宕机的问题,需要及时排查故障,采取相应的处理策略,并且完成后要及时进行监控和维护

15. Redis持久化的机制?

Redis提供了两种持久化机制:RDB和AOF。
RDB持久化会周期性地将Redis在内存中的数据集快照持久化到硬盘上,可以在需要时使用。AOF持久化会将Redis执行过的所有写命令记录到一个日志文件中,以便系统重启时能够重新构建数据集。
两种持久化机制各有优缺点,例如RDB能够更高效地进行数据恢复,但是如果过去的数据丢失,则将无法恢复。AOF则可以更好地保证数据持久化,但是使用更多的磁盘空间,写入日志的开销也可能会影响系统性能。
综合考虑,一般都会同时开启RDB和AOF持久化机制来保证数据的可靠性和高效性。

16. 底层是怎么保证不过期的?

17. 手撕:lc、 最长有效括号

二面:

18. 操作系统有进程,为什么还有线程?

操作系统中的进程(process)通常是指一个程序在执行过程中的一个实例,它拥有自己的内存空间、代码段、数据段、堆栈等数据结构,是系统资源分配和调度的基本单位。而线程(thread)则是进程的一部分,它在进程内运行,也拥有自己的堆栈、寄存器等,但是它们共享同一个地址空间,可以更高效地进行通信和共享数据。
为什么要使用线程呢?原因有以下几点:
1.线程可以在相同的地址空间内多个执行路径来执行不同的代码,提升了并发度,提高了系统的吞吐量和性能。
2.线程的创建和销毁的开销较小,处理上下文切换的成本也较低,因此可以更加高效地处理大量的并发请求。
3.在一些需要响应时间快的场景下,可以使用多线程来让用户享受更好更快的响应体验。例如在GUI应用程序中,使用单线程模型会使得界面因为长时间的等待而无法响应用户操作。
因此,虽然进程已经是系统的基本单位,但线程的引入可以更好地利用计算机的硬件资源,提高系统的并发处理能力和响应速度。

19. 什么是用户态、内核态?

用户态和内核态是计算机系统的两种不同的执行模式。用户态是指系统执行用户应用程序的模式,而内核态则是指系统执行内核代码的模式。

20. 什么情况从用户态到内核态?

当用户程序运行时,它处于用户态,此时它只能访问自己的内存空间和部分系统资源,而不能直接访问底层的硬件资源。如果需要访问底层硬件资源,则需要向操作系统内核发起系统调用,进入内核态。
而当内核进行系统调用处理时,它会从用户态切换到内核态,此时内核可以直接访问底层硬件资源和系统各种状态,处理完后再切换回用户态让用户程序继续运行。
用户态和内核态的切换需要耗费一定的系统资源,因此操作系统会尽量减少切换次数,提高系统运行效率。

21.进程通信方式

进程之间可以使用不同的通信机制进行通信,包括管道、命名管道、消息队列、信号量、共享内存、套接字等。其中,管道和命名管道可以实现单向通信,消息队列、信号量和共享内存可以实现双向通信,套接字可以实现跨网络的通信。例如,管道通信可以使用pipe()系统调用来创建管道,再使用read()和write()函数进行读写操作;而共享内存通信可以使用shmget()和shmat()等系统调用来获得共享内存区域的地址,再使用指针进行读写操作。不同的通信方式有各自的优缺点和适用场景,需要根据实际需求来选择。

22.Redis有持久化机制吗?

Redis提供了两种持久化机制:RDB和AOF。
RDB持久化会周期性地将Redis在内存中的数据集快照持久化到硬盘上,可以在需要时使用。AOF持久化会将Redis执行过的所有写命令记录到一个日志文件中,以便系统重启时能够重新构建数据集。
两种持久化机制各有优缺点,例如RDB能够更高效地进行数据恢复,但是如果过去的数据丢失,则将无法恢复。AOF则可以更好地保证数据持久化,但是使用更多的磁盘空间,写入日志的开销也可能会影响系统性能。
综合考虑,一般都会同时开启RDB和AOF持久化机制来保证数据的可靠性和高效性。

23. 手撕:lc10 、二叉树的锯齿形层序遍历

24. 接口

Java的接口是一种抽象类型,它定义了一组方法的签名但没有实现,这些方法可以在接口中声明为抽象方法或默认方法。接口可以被类实现来实现其方法,或者被其他接口扩展。接口的主要作用是定义类的行为规范,实现类必须遵守这些规范并提供方法的实现。接口还可以用于多重继承,一个类可以实现多个接口,从而继承多种行为。

25. 封装是解决什么问题?

封装是一种面向对象的编程概念,它主要解决的问题是控制对对象内部数据和方法的访问权限,以避免不必要的外部干扰和保护对象的内部实现细节。封装可以使对象的具体实现和使用时的接口相分离,降低代码的耦合性,增强代码的可维护性、可重用性和安全性。

二、超聚变 java实习软开 一面面经

1.你讲到了内存管理进程管理,简单说说内存置换算法

内存置换算法,主要有以下几种:
1。最优置换算法(Optimal):根据页面使用的情况和时序关系,置换出现未来最后被访问的页面。
2.先进先出置换算法(FIFO):按照页面进入内存的时间顺序进行置换。
3.最近最少使用置换算法(LRU):根据页面使用的情况和时序关系,置换最近最少使用的页面。
4.最不经常使用置换算法(LFU):根据页面使用的频率进行置换。
其中,最优置换算法具有最小的缺页率,但是实际应用中无法预测出未来的页面访问情况,因此不可行。FIFO算法简单易懂,但是缺点是可能会将重要的页面置换出去。LRU算法可以避免FIFO算法的问题,但是实现起来比较复杂。LFU算法则比较适合于长时间运行的程序和频繁访问某些页面的程序。

2.讲讲你的项目 讲了自己干了啥

3.你对你的项目有啥改进

4.有没有在linux上面开发项目

5.讲讲缓存击穿、雪崩、穿透及其解决方案

缓存击穿、雪崩和穿透都是缓存中经常出现的问题。
缓存击穿指的是一个热点数据的缓存过期后,短时间内有大量的请求涌进来,导致缓存失败并给后端带来很大压力。
雪崩则是指缓存服务器挂掉或重启导致大量请求被打到数据库上,导致数据库瞬间负载过高,甚至导致宕机。
而穿透是指缓存中查询一些不存在的数据,因为缓存中没有这些数据,每次查询都会打到数据库,容易导致数据库压力突然增大。
解决方案:
缓存击穿:可使用互斥锁或懒加载,即当缓存过期后,只允许一个请求到数据库去加载数据,其他请求等待这个请求返回缓存。另外,设置过期时间随机化,避免大批量数据同时失效。
雪崩:采用分布式缓存,部署多份缓存,避免单点故障。同时,采用多级缓存和热点数据预加载,减少缓存雪崩的风险。
穿透:使用布隆过滤器过滤掉不存在的数据,将不存在的数据直接返回,避免频繁查询数据库。同时,可将空值也缓存起来,缓存时间比较短,可以减少缓存穿透的风险。

6.项目里面最终一致性是啥意思

Java项目中的最终一致性是指,当多个副本之间的数据发生变化时,确保在一定时间内所有副本都能够达到相同的状态。这意味着在数据发生变化后,必须确保所有的副本都最终会达到一致的状态,即使存在一些短暂的不一致性。这种一致性通常是通过使用分布式事务进行实现的。

7.xxl-job调度怎么用的

xxl-job是一个分布式任务调度平台,通过调度中心统一管理任务的执行和调度。使用xxl-job需按照以下步骤:
1.在xxl-job中注册执行器。
2.在执行器中编写任务处理器,并实现任务执行逻辑。
3.在调度中心中配置任务,并设置任务的执行方式和执行参数。
4.在调度中心中启动任务。
通过以上步骤,xxl-job就可以按照指定方式执行任务并生成执行日志。

8.你提到了JVM 讲一下

JVM(Java虚拟机)是Java编程语言的核心运行时环境。它是一个虚拟的计算机,在计算机上运行Java字节码文件。JVM不直接与Java程序交互,而是与字节码进行交互,将其转换为计算机上的本机指令来执行程序。同时,JVM还提供了内存管理、自动垃圾回收、安全检查等功能。

三、100多人的公司面经

1.基本数据类型,所占的字节

Java中的基本数据类型和所占的字节数分别是:byte(1字节)、short(2字节)、int(4字节)、long(8字节)、float(4字节)、double(8字节)、char(2字节)、boolean(1位)。

2.ConcurrentHashMap的优点,与其他集合的不同

ConcurrentHashMap是Java中线程安全的哈希表,它比其他集合具有以下几点优点:
1.线程安全:ConcurrentHashMap是线程安全的,多个线程可以同时读写ConcurrentHashMap中的数据而不会出现线程安全问题。
2.高效性:ConcurrentHashMap采用分段锁技术,不同的线程可以同时访问ConcurrentHashMap的不同分段,从而提高了并发访问的效率。
3.高并发性:ConcurrentHashMap对于读操作不加锁,因此多个线程可以同时读取ConcurrentHashMap的数据,从而提高了并发访问的效率。
4.动态扩容:ConcurrentHashMap支持动态扩容,当元素数量超过容器大小的时候,ConcurrentHashMap会根据需要自动扩容。
与其他集合的不同之处在于ConcurrentHashMap是线程安全的哈希表,可以在高并发环境中保证线程安全并提高访问效率。而其他集合如HashMap、Hashtable、TreeMap等,在多线程环境中需要使用同步锁来保证线程安全,因此会存在性能瓶颈。

3.知道哪些线程安全list

Java中有以下线程安全的List:
1.Vector
2.CopyOnWriteArrayList
3.ConcurrentLinkedQueue
4.SynchronizedList
5.Collections.synchronizedList(List)

4.并发情况下,修改list会怎么样

在并发情况下,多个线程访问同一个List可能会导致修改冲突和竞态条件问题。具体来说,如果不采取措施确保线程安全,多个线程同时对同一个List进行修改操作,可能会导致数据不一致或抛出ConcurrentModificationException异常。
为了避免这种问题,可以采取以下几种措施:
1.使用线程安全的List类,例如CopyOnWriteArrayList或ConcurrentLinkedDeque。
2.在修改List的代码块上添加同步锁,例如使用synchronized关键字或ReentrantLock类。
3.使用并发集合框架,例如ConcurrentHashMap或ConcurrentSkipListMap,这些集合类已经考虑了并发修改的问题。
总之,在并发情况下,修改List需要特别小心处理,以确保线程安全和数据一致性。

5.创建线程池的方式,使用newSingleThreadExecutor创建线程的作用

创建线程池的方式有多种,常见的方式有newFixedThreadPool、newCachedThreadPool和newSingleThreadExecutor。其中,newSingleThreadExecutor方法会创建一个只有一个线程的线程池,在该线程池中所有的任务都将依次执行,保证顺序执行,并且确保不会有多个线程同时执行同一任务。该方法主要适用于需要按照顺序执行任务,而且任务量较小的情况下使用。

6.创建的数据结构有哪些

Java中常见的数据结构包括:数组(Array)、链表(LinkedList)、栈(Stack)、队列(Queue)、堆(Heap)、树(Tree)、图(Graph)等。其中数组是最简单的数据结构,其他的数据结构则可以基于数组或链表实现。每种数据结构都有对应的应用场景和优缺点

7.LinkedList的时间复杂度,如何将一条单链表的查询时间复杂度变成O(logn)

LinkedList的时间复杂度是O(n),但是如果采用类似二分查找的方法可以将查询的时间复杂度变成O(logn)。具体做法是,将链表按照节点的值排序,然后采用二分查找的方式进行查询。这需要维护一个有序的链表,如果需要在插入节点时保证链表的有序性,可以采用插入排序的方式。这样,在查询时就可以利用有序的链表进行二分查找了。

8.MySQL中的日志有哪些

MySQL中常见的日志有以下几种:
1.错误日志(Error Log):记录MySQL服务器的启动、运行和停止等过程中的错误信息。
2.查询日志(Query Log):记录MySQL服务器接收到的所有SQL语句,包括SELECT、INSERT、UPDATE、DELETE等。
3.慢查询日志(Slow Query Log):记录执行时间超过指定阈值的SQL语句。
4.二进制日志(Binary Log):记录所有对数据库进行的修改操作,包括INSERT、UPDATE、DELETE等。可以用于数据备份和复制。
5.中继日志(Relay Log):MySQL复制操作时,一台服务器将另一台服务器上的二进制日志中记录的修改操作发送到自己的中继日志中。
6.事务日志(Transaction Log):记录所有修改操作的执行前和执行后的内容,用于数据库的崩溃恢复和故障修复。
7.InnoDB引擎日志:包括redo log和undo log,记录InnoDB引擎日常运作中的修改和回滚操作等。

9.Spring中的IOC,举一个例子

在Spring中,我们可以使用IOC容器实现bean的自动装配,通过在xml配置文件或者注解中定义bean的依赖关系,Spring容器可以自动地将需要依赖的bean注入到目标bean中,从而简化了开发过程,提高了代码的可维护性和扩展性。例如,我们可以通过在xml配置文件中使用标签定义一个对象,并且在另一个对象中使用@Autowired注解来引用这个对象的实例。这样,当Spring容器启动的时候,它会自动地将需要依赖的对象装配到目标对象中,从而实现了对象之间的解耦和灵活性。

10.为何double,float会出现精度缺失

浮点数精度缺失的原因在于计算机中使用二进制数来表示实数,但二进制无法精确地表示某些十进制小数,例如0.1和0.01。这些十进制小数在二进制下都是无限循环小数,导致计算机在使用浮点数进行计算时出现精度缺失。double和float类型的浮点数的精度缺失程度不同,double的位数比float多,因此double的精度更高,但同时也会占用更多的内存空间。

11.String为何要使用final修饰,作用,存储方式,为何要在jdk9换成byte数组

String类中使用final关键字标记,这表示String类是不可继承的。此外,String类中的字符数组对象也是通过final关键字标记的,这表示String实例在创建后,其字符序列不能被更改。
使用final关键字可以避免String实例的字符序列被意外更改,从而保证String实例的不变性,这在并发编程等场景下非常重要。
在JDK8及之前版本中,String类的内部实现使用了字符数组存储字符串,而在JDK9版本中,String类的内部实现已经改为了字节数组。
换成字节数组的主要原因是,在Unicode中,一个字符可能需要2个或者4个字节来表示,因此在内存中存储大量的Unicode字符串会造成很大的内存开销。而使用字节数组则可以有效地减少内存占用。此外,字节数组的操作速度也比字符数组更快。

四、华为ODJava面经

1.左连接和右连接

左连接和右连接是关系型数据库的两种连接方式。左连接(Left Join)是指从左边的表中取出全部符合条件的数据,再将右边的表中符合条件的数据进行匹配;右连接(Right Join)则是从右边的表中取出全部符合条件的数据,再将左边的表中符合条件的数据进行匹配。这两者的区别在于哪个表被取出全部的数据。

2.查询语句优化

关于MySQL的查询语句优化,这里提供几个建议:
1.在创建表时,根据表中字段的特点选择适合的数据类型,避免过度浪费空间。
2.为经常使用的字段创建索引,可以有效提高查询的速度。
3.避免在WHERE语句中使用函数或者进行数学运算等操作,会降低查询性能。
4.尽量避免使用SELECT *语句,应该只查询需要的字段。
5.对于大数据量的表,可以考虑分区来优化查询速度。
6.在查询语句中使用JOIN时,应该优先考虑使用INNER JOIN而非OUTER JOIN。
7.避免在查询语句中使用LIKE '%value%'这种模糊匹配方式,可以使用全文检索或者正则表达式进行匹配。

3.谈谈对索引的理解,为什么用索引,什么情况下使用索引,索引的底层数据结构是什么,为什么用b+树,为什么不用红黑树,b+树和b树的区别

索引是数据库系统用来进行快速访问数据的一种数据结构,其作用是提高数据的检索速度。当数据表中的数据过多时,使用索引可以有效地加快查询和排序操作的速度。
在使用索引时需要考虑的因素包括查询的频率和数据表的大小。在数据表大小比较小的情况下,不使用索引可以快速访问数据;而在数据表大小较大时,使用索引可以大大加快查询和排序的速度。
索引的底层数据结构通常采用B树或B+树。B树是一种平衡树,它的特点是每个节点都可以存储多个数据项,并且节点的大小需要和磁盘块大小相匹配。B+树是在B树的基础上进行了优化,它的非叶子节点只存储索引项,而不存储具体的数据。这样一来,B+树可以更快地进行范围查找操作。
B树和红黑树都是平衡树,但B树更适合作为数据库索引的底层数据结构。这是因为B树更适合在磁盘上存储大量数据,并且B树更容易进行范围查找操作。而红黑树通常用于内存中的数据结构,因为它的平衡性更好,在内存中可以更快地进行各种操作。

4.数据库的隔离级别,分别解决了什么问题

数据库的隔离级别是指在多个并发事务同时访问同一个数据库时,各个事务之间的隔离程度。常见的隔离级别有读未提交、读已提交、可重复读和串行化。
读未提交:这个隔离级别下,一个事务可以读取另一个事务未提交的数据。这种情况可能导致脏读(读取到无效数据)和不可重复读(同一个事务内多次读取到的数据不一致)。
读已提交:这个隔离级别下,一个事务只能读取另一个事务已经提交的数据。这可以避免脏读,但是仍然可能出现不可重复读。
可重复读:这个隔离级别下,一个事务在执行过程中多次读取同一条数据时,得到的结果是一样的。这可以避免脏读和不可重复读,但是仍然可能出现幻读(读取到不存在的数据)。
串行化:这个隔离级别下,一个事务完全串行执行,每次只有一个事务能够执行。这可以避免脏读、不可重复读和幻读,但是效率较低。
因此,不同的隔离级别可以解决并发事务中的不同问题,开发人员需要根据具体场景选择合适的隔离级别。

5.Innodb和MyIsam的区别

InnoDB和MyISAM是MySQL数据库的不同存储引擎,二者的主要区别包括以下几个方面:
1.事务支持:InnoDB支持事务处理,可以使用ROLLBACK和COMMIT命令来控制数据的一致性,而MyISAM不支持事务处理。
2.锁机制:InnoDB采用行级锁定,可以大大提高并发性能并减少锁冲突,而MyISAM采用表级锁定,不能支持高并发环境。
3.外键支持:InnoDB支持外键,可以保证关联表数据的完整性,而MyISAM不支持外键。
4.性能表现:MyISAM在读取静态数据时性能较好,而InnoDB适合处理大量并发查询和更新的场景,同时对于频繁更新的应用InnoDB的性能也更好。
5.数据存储:InnoDB的数据存储方式比MyISAM更安全可靠,具有更好的容错性和恢复性,同时支持热备份和在线扩容,而MyISAM不支持在线备份和容错恢复

6.数据库事务的四个特性,其中原子性是什么意思

数据库事务的四个特性是原子性(Atomicity)、一致性(Consistency)、隔离性(Isolation)和持久性(Durability)。其中原子性指的是事务是不可分割的原子操作,要么全部执行成功,要么全部失败回滚,不会只执行部分操作。即事务是一个不可分割的最小单元,要么全部执行成功,要么全部取消回滚。这保证了事务执行的一致性和可靠性。

7.你了解的有哪些集合?

Java中常用的集合包括:List、Set、Map、Queue等。其中List可以有重复元素,Set不可以有重复元素,Map是键值对映射,Queue是队列实现。还有其他一些较为不常用的集合类,比如Stack、Vector等。

8.Arraylist和LinkedList的区别

ArrayList和LinkedList是Java中常见的容器类,它们都可以用于存储一组对象,但是它们之间有一些区别。
1.存储方式:ArrayList是使用数组来存储元素的,而LinkedList则是通过双向链表的方式来存储元素的。
2.随机访问速度:ArrayList支持随机访问,也就是可以通过下标快速访问其中的任意一个元素,而LinkedList由于是通过指针进行元素的遍历,因此访问速度较慢。
3.插入和删除操作:对于ArrayList,由于它是数组存储的,因此在中间插入或删除一个元素时需要移动其他元素的位置,会影响相应的效率,而LinkedList则通过改变链表的指针就可以完成元素的插入和删除操作,因此效率较高。
4.线程安全性:ArrayList是非线程安全的容器,而LinkedList是线程安全的容器。
综上所述,ArrayList适合查询操作较多的情况,而LinkedList适合插入和删除操作较多的情况。

9.HashMap的底层结构,put方法的具体操作过程

HashMap的底层结构是数组和链表(或红黑树),put方法具体的实现是将数组的每个元素都设置为链表的头节点,当hash冲突发生时,会将该元素添加到链表的末尾。put方法的具体操作过程是:首先通过key的hash值计算出在数组中的位置,然后遍历该位置上的链表或红黑树,找到对应的节点,如果存在则更新该节点的value值,如果不存在则创建一个新节点并添加到链表的末尾。如果链表的长度达到一定阈值(默认为8),则将链表转化为红黑树,以提高查找效率。最后,如果数组内元素数量超过了负载因子(默认为0.75),则进行扩容,并将原有的元素重新计算hash值,放入新的数组中。

10.了解CurrentHashMap吗

ConcurrentHashMap是Java中的一个线程安全的哈希表。它的作用是提供一个Map接口的实现,同时保证多个线程在进行操作时不会相互干扰。它通过将哈希表分成若干个段(Segment)来实现并发性,每个段内部都是一个独立的哈希表,而不同的段之间是相互独立的,这样就能在不影响整个表的情况下,实现线程间的并发访问。
ConcurrentHashMap在多线程环境下使用场景广泛,比如web服务器中缓存的使用、数据聚合、并行计算等。它不仅提供快速的查找、插入、删除等基本方法,还提供了一些高级特性,比如分布式锁、原子操作等。

11.谈谈Hashcode,==和equals的区别

Hashcode 是一个对象的哈希值,可以理解为对该对象的特定计算结果。等于(==)比较的是两个对象的引用地址是否相等,而 equals 是比较两个对象的内容是否相等。注意,如果一个类实现了 equals 方法,则必须同时实现 hashCode 方法,以保证对象在散列容器中能够正确工作。

12.创建多线程有什么方式?这些创建方式的区别是什么?

创建多线程有多种方式,其中常用的有以下几种:
1.继承Thread类并重写run()方法;该方式需要定义一个Thread子类并重写其run方法,然后通过创建该子类的实例来启动线程。
2.实现Runnable接口并实现run()方法;该方式需要定义一个类实现Runnable接口并重写其run方法,然后通过创建该类的实例以及一个Thread实例来启动线程。
3.实现Callable接口并实现call()方法,可获取返回值;
4.使用线程池创建线程。该方式将线程的创建和销毁等操作交给线程池管理,可以有效地减少线程的创建和销毁开销。
这些创建方式的区别主要在于如何创建和启动线程、是否能获取线程执行结果、是否能共享数据、是否支持返回值、是否能捕获异常等。可以根据具体的需求选择适合的方式来创建线程

13.线程池了解吗,说说线程池的具体工作过程

线程池是一种线程管理机制,它将多个线程保存在一个池中,用于执行可重用的任务,以提高线程的利用效率,降低线程的创建和销毁带来的开销。具体工作过程如下:线程池在启动时会创建一定数量的线程,并将其保存在一个池中,等待任务的到来。当一个任务到来时,线程池中的某个线程会被分配执行该任务,当这个线程完成任务后,它不会被销毁,而是返回线程池中等待下一个任务的到来。如果同时到来多个任务,线程池会根据一些算法和策略来决定任务的调度顺序和分配方式。通过线程池,可以有效地控制并发度,保证系统资源的合理利用,提高系统的性能和稳定性。

14.Java中有哪些锁,简单说说它们之间的区别

Java中有几种锁,包括内置锁(也称为监视器锁或对象锁)、可重入锁、读写锁、同步器等。这些锁之间的区别在于它们的实现方式、性能和适用场景等方面。具体来说,内置锁是Java中最基础的一种锁,通过synchronized关键字实现,适用于简单的线程同步;可重入锁通过ReentrantLock实现,支持重进入和超时等特性,适用于复杂的线程同步;读写锁通过ReentrantReadWriteLock实现,支持共享读,排它写等特性,适用于读多写少的场景;同步器则位于锁框架的最底层,提供更加灵活的锁控制方式。

15.JVM 的内存模型

JVM 的内存模型是指在 Java 中,由 JVM 管理的内存区域以及内存访问的规范。它定义了线程如何与内存交互,以及两者之间的内存可见性等问题。JVM 的内存模型主要包括程序计数器、Java 虚拟机栈、本地方法栈、堆、方法区等几个部分。其中,堆是 Java 程序中最大的内存区域,用于存储对象实例及数组等数据。而 Java 虚拟机栈则用于存储每个线程执行方法的栈帧。JVM 的内存模型为 Java 程序提供了高效、安全的内存管理机制。

16.JVM的垃圾回收算法

JVM的垃圾回收算法主要有以下几种:
1.标记-清除算法(Mark-Sweep):先标记出活跃对象(可达对象),再清除未被标记的对象。该算法会产生大量的内存碎片,因此长时间使用后可能会出现内存不足的问题。
2.复制算法(Copying):将活跃对象复制到新的内存空间中,然后将原来的空间全部清除。该算法的优点是速度快、内存利用率高,但是只适用于对象存活率较低的情况。
3.标记-整理算法(Mark-Compact):先标记出活跃对象,然后将活跃对象向内存的一端移动,最后清除未被标记的对象并对内存进行整理。该算法适用于存活对象较多的情况。
4.分代算法(Generational):将堆内存分为新生代和老年代,针对不同代采用不同的垃圾回收算法。新生代采用复制算法,老年代采用标记-清除或标记-整理算法。
这些算法的应用场景主要取决于应用程序的对象分配和使用特点,以及垃圾回收机制的实现细节。比如,对于对象存活率较低、对象分配和回收比较频繁的场景,可以采用复制算法;对于存活对象较多、内存空间不足的场景,可以采用标记-整理算法。

17.双亲委派模型

双亲委派模型是一种Java类加载器的实现机制,通过父类加载器和子类加载器的层级关系,在程序运行期间动态加载并管理不同的类库。具体而言,当一个类被加载时,被委派给它的父类加载器首先尝试去加载该类,只有在父类加载器无法加载该类的情况下,才会由子类加载器尝试去加载。这种模型既能保证类的隔离性,又能避免同一个类被多次加载,提高代码的可复用性和性能。

五、阿里菜鸟java实习电话二面

1.OSI七层网络模型以及各层的作用

OSI七层网络模型是一种将网络通信划分为不同层次的标准,它将网络通信过程划分为七层,每一层都有特定的功能和责任,便于网络协议的设计、实现和维护。各层的作用如下:
1.物理层:负责传输比特流,包括物理介质、电气特性、传输速率等。
2.数据链路层:提供透明的比特流传输,保证数据的可靠传输,包括数据的分帧、差错校验、流控制等。
3.网络层:负责数据包的路由选择和转发,实现跨子网的通信,包括地址识别、路由选择、拥塞控制等。
4.传输层:提供端到端的可靠、透明的数据传输,包括流量控制、差错校验、数据重传等。
5.会话层:管理会话的建立、维护和结束,包括同步、检查点和恢复等。
6.表示层:负责数据的编码与解码,提供数据格式转换、数据加密和解密、压缩和解压缩等服务。
7.应用层:提供用户接口,定义用户与网络之间的接口协议,使用户能够访问网络资源。

2.TCP和UDP的区别

TCP(传输控制协议)和UDP(用户数据报协议)都是互联网传输协议,但它们有很大的区别。TCP是面向连接的协议,提供可靠的数据传输,它在传送数据前先建立连接,而且在传送过程中会对数据进行检验、重传、排序等处理,以保证数据的正确传输。UDP则是无连接的协议,不保证数据传输的可靠性,它只是把应用程序传给网络层的数据报发送出去,但是并没有确认是否到达目的地。另外,TCP传输速度慢、效率低,但是可靠性高,广泛用于文件传输、电子邮件、网页浏览等应用;UDP传输速度快、效率高,但是可靠性低,适用于视频、语音、在线游戏等实时性要求较高的应用

3.TCP保证可靠传输的机制

TCP使用以下机制保证可靠传输:
1.确认和重传机制:发送方发送数据后,等待接收方的确认消息;如果一定时间内没有收到确认,发送方就会重传数据。
2.滑动窗口机制:接收方会给发送方返回一个窗口大小,发送方发送的数据不能超过窗口大小,确认后窗口会向前滑动。
3.流量控制机制:当接收方暂时不能接收数据时,发送方会根据接收方返回的窗口大小调整发送速度,以保证不会造成网络拥塞。
4.拥塞控制机制:当网络出现拥塞时,TCP会逐步降低发送速度,以减少网络拥塞导致的数据丢失率。

4.TCP三次握手机制

TCP三次握手是TCP协议中用于建立可靠连接的一种方法。这种连接是点到点的,全双工的连接。它需要进行三次握手以便在客户端和服务器之间建立一个可靠的连接。第一次握手是由客户端向服务器发送一个同步包(SYN)来开始一个连接。第二次握手是由服务器回应一个同步/应答包(SYN/ACK)来确认客户端请求的连接。第三次握手是由客户端再次向服务器发送一个应答包(ACK),确认服务器回应的应答包。当三次握手完成之后,客户端和服务器之间的连接就建立了,可以开始传输数据。

5.进程与线程之间的区别

进程和线程是操作系统中的两个基本概念,它们都是为了完成多任务操作而存在的。
进程是一个正在运行中的程序,它包含了程序执行所需的代码、数据以及有关运行状态的信息。每个进程都是独立的,拥有自己的地址空间,可以与其他进程并行执行。
线程则是进程中的可执行代码片段,它可以看作是一个轻量级的进程。与进程不同的是,同一进程中的所有线程共享相同的地址空间和其他资源,可以并发执行,常用于提高程序的并发性和效率。
简单来说,进程是计算机中能够获得 CPU 时间、内存等资源分配的基本单位,线程是进程中独立的执行流程,多线程可以共享进程所拥有的资源,提高程序效率。

6.进程之间的通信方式有哪些

进程之间的通信方式有以下几种:
1.管道(Pipe):管道是一种半双工通信方式,只能用于有亲缘关系的进程间通信。
2.命名管道(FIFO):命名管道也是一种半双工通信方式,可以解决无亲缘关系进程之间的通信问题。
3.消息队列(Message Queue):消息队列是一种通过在进程之间发送消息的方式进行通信的机制。
4.共享内存(Shared Memory):共享内存是最快的一种IPC通信方式,它是一块公共内存区域,多个进程可以同时访问同一块内存,以达到数据共享的目的。
5.信号量(Semaphore):信号量是一种计数器,用于多个进程之间的同步以及共享资源的访问。
6.套接字(Socket):套接字是一种可以在不同主机之间进行通信的方式,常用于网络通信

7.AQS的底层原理

AQS (AbstractQueuedSynchronizer) 是一个用于实现同步器的基类,它的底层原理是使用一个双向链表来存储等待线程,使用 CAS (Compare and Set) 操作来修改同步状态,实现线程的加锁和解锁操作。具体来说,AQS 在同步器类中定义了一个 state 变量,用于表示同步状态,同时定义了 acquire 和 release 两个方法,分别用于线程的加锁和解锁操作。当一个线程需要进行加锁操作时,它将会调用 acquire 方法,在方法中通过 CAS 操作将 state 设为加锁状态,同时将当前线程加入到同步队列中,如果 CAS 操作失败,则说明当前锁已经被其他线程占用,线程将会被挂起,进入等待状态。当一个线程需要进行解锁操作时,它将会调用 release 方法,在方法中通过 CAS 操作将 state 设为解锁状态,同时唤醒等待队列中的下一个线程。这样,通过 AQS 的底层同步机制,就能够实现线程的安全同步。

8.线程中的原子性、可见性、有序性都是怎么实现的

线程中的原子性、可见性、有序性是由Java内存模型(JMM)来实现的。
原子性是指一个操作在执行过程中不会被中断,要么执行完毕,要么不执行。Java的原子性操作有很多,如AtomicInteger、AtomicBoolean、AtomicLong等,它们使用了硬件级别的CAS(Compare and Swap)指令来保证原子性。
可见性是指当一个线程修改了共享变量的值时,其他线程能够立即看到这个变化。Java通过volatile关键字和synchronized关键字保证可见性。
有序性是指程序执行的顺序按照代码的先后顺序执行,也就是保证了内存操作的顺序性。Java通过volatile关键字和synchronized关键字保证有序性。此外,Java还提供了一些工具类来帮助程序员调度线程的执行顺序,比如CountDownLatch、CyclicBarrier等。

9.volatile单例模式和指令重排是什么

Volatile单例模式是一种线程安全的单例模式,在多线程环境下保证只有一个实例被创建。指令重排是处理器为了提高指令执行效率而进行的重排优化,导致指令的执行顺序与程序的书写顺序不一致,可能会对多线程程序的正确性产生影响。在单例模式中,如果不使用volatile关键字修饰实例变量,可能会导致指令重排造成线程安全的问题。因此,在使用单例模式时,需要注意实例变量的声明并使用volatile关键字进行修饰,以免出现线程安全的问题

10.synchronized和lock的区别

synchronized 和 lock 是两种不同的同步方法。
synchronized 是 Java 中的关键字,是一种内置的同步机制。它可以保证一个时刻只有一个线程执行同步代码。使用 synchronized 可以很容易地保证线程安全,但是它有一些限制,例如不支持超时等待和不可中断的锁获取。
Lock 是 Java 中的一个接口,提供了一种比 synchronized 更加灵活的同步机制。它支持超时等待和可中断的锁获取,可以更好地管理线程同步。但是使用 Lock 需要更多的代码编写,并且需要注意避免死锁等问题。
总的来说,synchronized 比较简单,适合简单的同步场景;而 Lock 更加灵活,适合复杂的同步场景。

11.Java中如何解决ABA问题

ABA问题是指在并发编程中,一个值由A变成B,再由B变回A,但是在这整个变化过程中,有其他线程将这个值也修改了,导致程序无法意识到这个变化过程中发生了其他线程的修改,从而可能导致一些错误的结果。Java中解决ABA问题的方式是使用AtomicStampedReference类,它可以将一个对象的引用和一个整数(称为时间戳)一起打包,确保在多线程环境下引用的修改是有序、有状态的。当需要对对象进行修改时,必须同时更新对象的引用和时间戳,这样就可以避免ABA问题的出现。

12.脑筋急转弯:五个人过河的经典问题。

六、趣链科技java实习一面(武汉)

1.java集合有哪些

Java集合框架包括以下类别:
1.List(列表):存储有序的元素,允许重复元素。
2.Set(集合):存储无序的元素,不允许重复元素。
3.Queue(队列):用于在队列中添加或移除元素,通常按照“先进先出”(FIFO)的原则来操作。
4.Deque(双端队列):是Queue接口的扩展,可以从两端添加或移除元素。
5.Map(映射表):存储键值对,不允许同一键出现多次,但是允许不同的键对应相同的值。
常见的集合类包括:
1.ArrayList:可重复、有序的列表。
2.LinkedList:可重复、有序的列表,操作效率较高。
3.HashSet:不可重复的集合,不保证顺序。
4.TreeSet:不可重复的集合,按照元素的自然顺序进行排序。
5.PriorityQueue:基于堆的队列,按照元素的优先级进行存储和访问。
6.ArrayDeque:双端队列,可在队列的两端进行操作。
7.HashMap:具有映射关系的键值对,键不可重复。
8.TreeMap:具有映射关系的键值对,按照键的自然顺序进行排序。

2.PriorityQueue属于哪种集合,底层怎么实现的

PriorityQueue属于队列集合,底层是通过堆来实现的。具体地说,PriorityQueue是基于优先级堆数据结构实现的,每次插入一个元素时,元素会根据其优先级(通过实现Comparable接口或传入Comparator对象来自定义元素比较方式)被放入堆中的适当位置,而不是按照插入顺序排列。在删除元素时,PriorityQueue总是删除堆中优先级最高的元素(即堆顶元素),因此其获取元素的顺序是根据优先级的排序。

3.说一下MySQL

MySQL是一种开源的关系型数据库管理系统,它支持多用户、多线程和多种不同的存储引擎。MySQL被广泛应用于Web应用程序开发中,尤其是在LAMP(Linux、Apache、MySQL和PHP/Python/Perl)堆栈中。MySQL可通过SQL语言进行访问和管理,可以用于存储、排序、过滤和查询大量数据。

4.MySQL有哪些存储引擎,默认用哪种?

MySQL有多种存储引擎,其中比较常见的包括 MyISAM、InnoDB、Memory等等。5.5及之前的版本默认使用MyISAM,5.6及之后的版本默认使用InnoDB。

5.MySQL怎么实现分页查询的,具体怎么实现?

MySQL实现分页查询可以使用LIMIT和OFFSET关键字,其中LIMIT表示每页显示的记录条数,OFFSET表示从哪条记录开始,例如查询第11-20条记录:
SELECT * FROM table_name LIMIT 10 OFFSET 10;
其中LIMIT 10表示每页显示的记录数为10条,OFFSET 10表示从第11条记录开始查询。
另外,也可以使用LIMIT和OFFSET组合的简写语法:
SELECT * FROM table_name LIMIT 10, 10;
同样表示查询第11-20条记录,其中10表示OFFSET,10表示LIMIT。

6.MyBatis配置文件需要配置哪些

MyBatis配置文件至少需要配置以下内容:
1.数据库连接信息:包括数据库URL、用户名和密码等。
2.数据库连接池配置:包括连接池的大小、最小连接数、最大连接数等。
3.MyBatis运行环境配置:包括事务管理器、缓存管理器等。
4.Mapper文件配置:包括Mapper文件的路径、资源引用方式等。
5.全局配置:包括日志输出、数据库方言等。
6.插件配置:可以配置插件来扩展MyBatis的功能。
注意:以上仅为常见的配置信息,并非全部。配置文件的具体内容还需根据实际情况而定。

7.Lucene是什么,用来干啥的

Lucene是一个Java语言编写的全文搜索引擎库,它提供了高效、强大、灵活的文本搜索和索引功能,可以轻松地实现全文搜索、文本相似度匹配、自动补全等功能。Lucene可以被应用于各种不同的领域,如信息检索、文本挖掘、文本分类、自然语言处理等。

8.Lucene底层怎么实现的

Lucene底层主要是通过倒排索引实现的。这个过程可以分为三个步骤:首先是分词,将文本按照一定规则进行切分;接着是建立索引,将分词后得到的关键词和它们所在的文档建立映射关系;最后是检索,通过查询词找到匹配的文档。Lucene底层的倒排索引提供了高效的文本检索能力,广泛应用于全文检索系统的实现。

9.SM搭建过程,自己可以搭建吗

10.Redis是什么,用来干什么的?

Redis是一个开源的高性能键值对存储系统,用于在内存中存储数据,提供快速读写性能。它可以用来做缓存、消息队列、实时统计等各种应用场景。Redis支持持久化存储,可以将数据写入磁盘保证数据不丢失。同时,Redis具有多种数据结构(如字符串、哈希、列表、集合、有序集合等等),可以灵活地满足各种业务需求。

你可能感兴趣的:(每日面试题刷,笔记,java,jvm)