Java开发一些偏冷门的面试题

主要从别人的面经那里看来的,以及自己被问住的一些面试题。
拿出来给自己做记录,也顺便给大家做参考!

1.进程间的通信,线程间的通信

这个题是面猿辅导时候被问到的,先是被问了进程和线程的区别,后来问到了管道,用自己模糊的本科时期的记忆回答了一下,管道本质上是要考进程通信。

首先可以先回答进程、线程和协程

  1. 进程是程序启动的实例,进程之间相互独立。进程之间是相互隔离的,不能直接共享数据。
  2. 线程是程序实际的执行者,一个进程最少要有一个线程。
  3. 协程是一种轻量级的线程,它可以在同一个线程内执行多个任务,而不是使用多个线程。协程通常被称为"用户态线程",因为它们由应用程序代码来管理,而不是由操作系统内核来管理。
  4. 关于空间:进程有自己独立的堆空间、线程有自己独立的栈空间,进程之间不能直接进行信息共享,同一进程之间的线程可以共享堆空间。

关于线程和进程通信

进程通信:首先要明确的是进程之间不能进行直接的信息共享,同时进程很有可能来自不同的服务甚至不同的机器(比如QQ和微信就是两个进程)。所以进程之间的信息共享可以利用一些网络通讯,比如利用消息队列MQ、基于socket套接字。如果整狠活可以利用共享内存来进行通讯,但需要谨慎处理同步问题。
线程通讯:多个线程在同一进程中可以通过共享内存来实现通信。这通常需要使用锁(如互斥锁、读写锁)来确保数据一致性。信号量是一种计数器,用于控制同时访问共享资源的线程数量。它可以用于线程之间的互斥和同步。
最后你要好好讲讲管道!

管道的本质是一种数据流通道,它用于在进程之间或线程之间传递数据。管道是操作系统提供的一种通信机制,它允许一个进程或线程将数据写入一个端口,同时另一个进程或线程可以从另一个端口读取相同的数据。
单向通信: 管道通常是单向的,有一个写入端和一个读取端。数据从写入端流入,然后从读取端流出。
阻塞操作: 当管道为空时,读取操作可能会被阻塞,直到有数据可读。同样,当管道已满时,写入操作可能会被阻塞,直到有足够的空间可用。
FIFO(先进先出): 管道通常采用先进先出的原则,确保数据的顺序保持一致。

2.MySQL中的缓存情况,以及缓存命中率查询

这个是看到了别人的面经(应该是滴滴的面经)

MySQL数据库中有多种缓存机制,这些缓存有助于提高查询性能和降低数据库服务器的负载。与其他缓存类似他也是在内存中开辟空间进行缓存的存放,最主要的是innoDB缓冲池。
InnoDB缓冲池(InnoDB Buffer Pool):它使用一个称为缓冲池的内存区域来缓存数据和索引。缓冲池用于加速对表数据的读取和写入操作,减少了磁盘 I/O 的次数,从而提高了性能。
查询缓存(Query Cache): 查询缓存是 MySQL 中的一个可选组件,用于存储以前执行的 SELECT 查询的结果集。如果一个查询在查询缓存中找到匹配项,MySQL 将返回缓存中的结果,而不会执行实际的查询。尽管查询缓存可以提高查询性能,但它在高并发和频繁更新的情况下可能会导致性能下降,因此在新版本的 MySQL 中已经被弃用。
剩下的还有键缓存、表缓存、日志缓存等…
关于配置: InnoDB 存储引擎使用一个称为缓冲池的内存区域来缓存数据页和索引页。缓冲池的大小可以通过配置参数 innodb_buffer_pool_size 来设置。
程序员可以通过SHOW STATUS进行性能信息统计

SELECT (Qcache_hits / (Qcache_hits + Com_select)) * 100 AS cache_hit_ra

% Com_select:这个变量表示执行的 SELECT 查询次数。
% Qcache_hits:这个变量表示查询缓存命中的次数。

SHOW VARIABLES 命令: 使用 SHOW VARIABLES 命令可以查看 MySQL 的配置变量。你可以查看以下两个与查询缓存有关的变量:
query_cache_type:这个变量表示查询缓存的类型,通常为 ON 表示开启。
query_cache_size:这个变量表示查询缓存的大小。
另外还可以使用一些外部的检测工具进行数据库情况的统计。

3. InnoDB B+树中大概能存放多少条索引记录

这个是来自知乎面试的一个面试题,原题目是:InnoDB中一行数据1kb,两层B+树大概能存放多少数据。
首先要确定的一点是innoDB引擎下一个页默认大小是16KB;同时InnoDB引擎采用的是非聚集索引,即非叶子节点中存放的是指针和索引,叶子节点上存放的是数据。

假设一条记录大小为1KB,则一个数据页中可以存16条数据(忽略页中的其他数据结构)
主键为int(32Bit)类型,一个指针大小为6B,一个索引中可以存放16KB/(4B+6B)=1638个索引,即B+树中一个节点能存放1638个索引。
两层能存放161638条1kb数据
三层能存放16
1638*1638条1kb的数据

3. volatile关键字如何保证可见性与有序性

来自于知乎的一道面试题,不过这个题也不能算得上是冷门题
首先要确定的是volatile在并发编程的两大特性:

1.保证在多线程环境下共享变量的可见性
2. 禁止多线程环境下CPU的指令重排

如何保证可见性

当对volatile关键字进行写操作时,JVM会向处理器发送一条#LOCK前缀的指令,并直接将这个变量写回系统主存中(每次变更都会强制写回主存)。其他处理器的缓存由于遵守缓存规则一致性协议,它会从主内存中获取最新的值,而不是使用线程本地的缓存。

如何保证有序性

为了优化程序性能,编译器和处理器会对java编译后的字节码和机器指令进行重排序,通俗的说代码的执行顺序和我们在程序中定义的顺序会有些不同,

保证有序性其实就是如何防止指令重排,volatile利用内存屏障机制来实现有序性
在volatile写操作之前插入StoreStore屏障,他会要求后面指令执行时,前面的指令必须都执行完并写到主存中。
volatile写操作之后插入Storeload屏障,指令前的变量刷新到主存中,后面的指令才能读

写过程
普通写 --> StoreStore屏障 --> volatile写 --> Storeload屏障 --> 普通读
读过程
volatile读 --> StoreLoad屏障 --> StoreStore屏障 --> 普通读 --> 普通写

单核CPU是否有线程安全问题

知乎面试题
单核CPU的Java程序在某些情况下也可能出现线程安全问题,尽管单核CPU限制了并行性,但线程安全问题仍然可能发生。这是因为线程安全问题通常是由多个线程对共享数据进行并发读写操作引发的,而不仅仅是并发执行的问题。

1.共享数据:如果多个线程同时访问和修改共享的数据结构或变量,无论CPU是单核还是多核,都可能导致线程安全问题。这包括类级别的静态变量和实例级别的成员变量。
2.线程交互:即使是单核CPU,也可能出现多个线程之间的交互问题。例如,一个线程在某个时刻执行了一半的操作,然后被另一个线程抢占执行,这可能导致不一致的状态。
3.不可见性问题:即使是单核CPU,由于编译器优化、CPU缓存和指令重排序等原因,某些变量的更改可能对其他线程不可见,导致不一致的行为。
4.原子性问题:某些操作需要在一个原子操作内完成,例如递增一个计数器。即使是单核CPU,如果这个操作被多个线程并发执行,也可能导致竞争条件和线程安全问题。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

ZATuTu丶

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值