字节跳动Java大厂面试版

张开发
2026/4/17 7:06:15 15 分钟阅读

分享文章

字节跳动Java大厂面试版
1、 ThreadLocal1.1 谈谈你对ThreadLocal的理解ThreadLocal的作用主要是做数据隔离填充的数据只属于当前线程变量的数据对别的线程而言是相对隔离的。它不是针对程序的[全局变量]只是针对当前线程的全局变量。1.2 ThreadLocal底层实现原理Threadlocal内部有一个非常关键的[内部类]ThreadlocalMap里面定义了一个由key - value组成的Entry数组key存放的就是当前的线程value为我们所需的数据。 而key是弱引用会被gc清除value是强引用不会被清除所以会造成内存泄漏。如果我们在线程池中使用了Threadlocal一定要记得调用remove方法避免ThreadLocal 保存的数据被泄漏或污染scsspublic void set(T value) {//进行set方法时先获取当前线程对象根据当前线程获取ThreadLocalMap//然后以当前Threadlocal为key进行存储Thread t Thread.currentThread();ThreadLocalMap map getMap(t);if (map ! null)map.set(this, value);elsecreateMap(t, value);}AI写代码2、synchronized相关问题2.1 synchronized与Reentrantlock的区别synchronized是一个关键字属于JVM层面的Reentrantlock是一个类是API层面的synchronized是自动加锁、释放锁Reentrantlock则需要手动加锁和释放synchronized底层有一个锁升级的过程偏向锁—轻量级锁----重量级锁当一个线程获取一个琐时此时该锁为偏向锁当第二个线程尝试获取锁时该锁会升级为轻量级锁,底层通过自旋来实现不会造成线程阻塞,当自旋次数过多会升级为重量级锁会造成线程阻塞。2.2 volatile关键字如何保证可见性和有序性可见性对加了volatile的成员变量进行修改时会直接将cpu高级缓存区的数据放到主内存中对这个数据的读取会直接从主内存中取。有序性对加了volatile的成员变量进行读写时会插入内存屏障防止指令重排保障了有序性。volatile只有写操作是原子性的也就是数据操作完成后会立刻刷新到主内存中。但是被volatile修饰的变量在读的时候可能会被多个线程读,所以它不能保证原子性。2.3 Java如何避免死锁注意加锁的顺序保证每个线程按顺序进行加锁加锁时限可以设置一个超时时间注意死锁检查这是一种预防机制可以确保发生死锁的第一时间进行处理。[]3、 多线程线程池由于篇幅限制笔记无法全部为大家展示出来就以截图主要内容的形式让大家参考啦需要完整版的小伙伴可以点击https://github.com/encode-studio-fe-coder/natural_traffic/wiki/scan_material13获取文章中的文档和资料3.1 线程有哪些状态生命周期新建、就绪、运行、阻塞、死亡3.2 如何获取多线程的返回值深坑如果问多线程的创建方式你一定知道是继承Thread类实现runnable,callable接口。这里就是拐了个弯变相的了解有返回值的callable接口。通过中间媒介FutureTask将实现callable接口的类对象传递进去调用FutureTask里面的get方法即可获取多线程的返回值。3.3 为什么使用线程池几个参数降低资源消耗创建、销毁耗资源提高响应速度任务来了可以有线程直接使用核心线程数、 最大线程数量、最大空闲时间、 空闲时间单位、任务队列、 线程工厂、拒绝策略4、并发相关问题4.1、 并行、串行、并发并行 同一时刻多个任务互不干扰的同时进行串行任务排队一个一个执行并发同一时刻只有一个任务多个任务交替执行4.2、 谈谈对AQS的理解AQS如何实现可重入锁AQS是一个Java线程同步的框架是JDK很多锁的核心实现框架。在AQS中,维护了一个信号量state和一个由线程组成的双向链表队列。其中这个线程队列就是给线程排队的而state就像是红绿灯用来控制线程排队或者放行的。不同场景下有不同的意义。在可重入锁锁了还可以再锁场景下state表示加锁次数0表示无锁每加一次锁state就加1释放锁state就减1。点击阅读 [并发编程小结]三、mysql相关问题笔者总结了一篇Mysql高级涉及内容较深些也是常问的面试题点击链接查阅[Mysql高级篇]1、Mysql索引1.1 索引的类型可以是String类型吗聚簇索引----数据和索引放一块像主键索引具有唯一性Innodb就是数据库第一范式必须要有id这个id是自带索引的。一般用自增id字符串可以做id但是不好像uuid做的id是随机的都没有排序不像自增id维护索引的成本会很低1.2 什么是索引什么情况下用索引什么时候不用1就是一种数据结构目的就是为了快速查找数据。2对查询频率高索引就是为了提高查询效率像where后的字段数据量特别大 索引不是越多越好会影响增删的效率典型的用空间换时间。分组字段可以建立索引因为分组的前提是排序覆盖索引3频繁更新的字段、查询少的、参与计算的不适合建索引。1.3 索引失效在MySQL中查询不走索引可能有以下几种情况数据量太小如果表中的数据量比较小MySQL会选择进行全表扫描而不使用索引因为全表扫描的开销可能比使用索引更小。 对索引列进行了函数操作如果在查询语句中对索引列进行了函数操作或表达式运算MySQL无法使用索引进行优化因此可能不走索引。 范围查询如果查询语句中包含范围查询例如大于、小于、区间查询等MySQL可能无法使用索引进行优化导致不走索引模糊查询like,%前置不会走后置会走。 数据分布不均匀如果索引列的数据分布不均匀索引的选择性较低MySQL可能选择进行全表扫描而不使用索引。在进行MySQL索引优化时需要考虑以上情况并通过分析查询语句、优化索引设计、适时更新统计信息等方法提高MySQL查询性能尽可能减少不走索引的情况。1.4 查看索引使用和查看索引信息索引使用 explain 结果 只要数字大于11 row in set 即生效了查看索引信息 show indexs from 表名1.5 复合索引最左匹配原则最核心的是等值比较复合索引就是多个字段放一块企业最常用的是符合索引唯一索引普通索引我们也用mysql会一直向右查询直到遇到范围查询 like比如用 a b c d四个字段创建了一个复合索引 a3 b5 c7 d9 只会用到前三个因为b c d 是根据a 的后面进行规则的排序即a是有序的后面的bcd是无序的。 hash索引用的不多因为无序但是定位快了解即可1.6 Btree和Btree为什么mysql用的是B tree**Btree是Btree的升级版。Btree多路平衡树当增删数据时会自动的将数据进行这个平衡旋转为什么从Btree转到Btree? 因为索引也是一个文件存档在磁盘在使用时读入到内存。内存是有限的如果索引文件过大无法一次性全部加载需要分批加载。在有限磁盘的限制下Btree可以减少磁盘的I/O。对于Btree所有的数据都存在叶子节点根和非叶子节点只是存储的指针指向下一个数据的地址由叶子节点再去查找到关联的数据信息。对于查询的数据都要从root节点走到叶子节点所以查询相比于Btree更加稳定。对于mysql是在Btree的基础上在相邻节点间增加了一个链表指针形成了带有顺序的Btree,提高了区间的访问性能。1.7 覆盖索引与回表如果只需要在一棵索引树上就可以获取Sql所需要的所有列就不需要回表查询这样查询速度会更快。而实现覆盖索引最快的方式就是将所需要的字段放在一起建一个联合索引。1.8 Mysql的锁有哪些什么是间隙锁从锁的粒度来分1、行锁加锁粒度小但是加锁的资源开销比较大。Innodb支持。1共享锁多个事务可以共享一把锁但是只能读不能修改2排他锁只有一个事务可以获得排他锁其他事务不能获取该行的锁。Innodb会自行对增删改操作添加排他锁。2、表锁加锁粒度大加锁的资源消耗小Mysalm和Innodb都支持。3、全局锁加锁后全库都处于只读状态用于全库数据备份。1.9 海量数据下如何快速找到一条数据1使用布隆过滤器快速过滤不存在的数据2red is中建立数据缓存3查询优化2、数据库分库分表2.1 数据库的分库分表什么时候分怎么分当单表数据超过1000W时很多操作的性能会下降所以需要切分以减少数据库的压力缩短查询时间。垂直切分将关系联系不紧密的表进行分库将一张表中不常用的字段进行抽取新建一张表。优点类似于微服务。水平切分当一个应用难以再细粒度的垂直切分根据数据间的逻辑进行划分比如客户、存款、支付2.2 数据库的优化?1sql优化以及索引的优化索引建立要合理过多会影响增删性能2数据可设计要满足他的三大范式、五大约束3硬件优化由于篇幅限制笔记无法全部为大家展示出来就以截图主要内容的形式让大家参考啦需要完整版的小伙伴可以点击https://github.com/encode-studio-fe-coder/natural_traffic/wiki/scan_material13获取文章中的文档和资料在设计数据库表时需要注意以下几点特别是在定义字段的时候数据类型选择选择最适合的数据类型可以减小数据库表的存储空间提高检索效率。对于整数、浮点数、字符串等不同类型的数据选择合适的数据类型是设计表结构时的关键之一。 索引设计根据实际查询需求设计合适的索引可以提高查询效率。通常在主键、外键、经常用于查询的字段上创建索引。 主键设计选择一个唯一、稳定、易于理解的字段作为主键以确保每条记录都有唯一标识便于数据访问和管理。 字段命名规范字段命名应具有描述性易于理解和记忆建议使用下划线分隔如first_name避免使用含糊不清或缩写的字段名。 字段约束定义字段的约束条件如NOT NULL、UNIQUE、DEFAULT值等可以保证数据的完整性和一致性。 数据冗余避免数据冗余尽可能将重复的数据抽取成单独的表以减小数据存储量同时避免数据更新异常。 参照完整性在设计外键关系时保证参照完整性确保相关数据的一致性避免数据关联异常。 考虑数据增长预估数据表的增长情况选择适当的存储引擎和分区方案以支持未来数据量的增长。综上所述在设计数据库表结构时字段的数据类型、索引设计、主键选择、命名规范、约束条件、数据冗余、参照完整性、数据增长等方面都需要认真考虑以保证数据库表的稳健性、性能和灵活性。[]3、数据库事务spring里面的事务和mysql里面的事务是一个概念如果mysql不支持事务加上transation也是无效的。但是spring里面的transation不能用于分布式环境下分布式多线程下用的是sentaglobalTransation注解。3.1 transation用于类和方法有什么区别transation只能修饰public方法。类上相当于在所有的public方法上加上了transation注解方法会覆盖类上的配置。3.2 事务的4个条件ACID原子性所有的操作是一个整体要么全部成功要么全部失败回滚一致性事务开始前后数据库的完整性没有被破坏也就是写入的资料完全符合我们的预设。隔离性允许多个并发事务对数据进行读写操作它可以有效的防止多个事务并发执行时由于交叉执行而导致数据的不一致。隔离性里面有4个隔离级别读未提交、读以提交、可重复读、串行化持久性事务完成对数据的操作就是永久的即使系统故障也不会丢失。3.3 mysql事物隔离级别MySQL 提供了四种隔离级别用于控制事务之间的隔离程度以确保事务操作的一致性和并发性。这四种隔离级别分别是读未提交Read Uncommitted 最低的隔离级别允许一个事务读取另一个事务未提交的数据。可能会出现脏读Dirty Read问题。 读提交Read Committed 其他事务提交后才能读取数据避免脏读问题。但可能会出现不可重复读指的是在同一个事务中某个查询操作在不同时间点内多次执行但由于其他事务的并发操作在多次执行过程中返回的数据结果不一致的情况问题。 可重复读Repeatable Read 保证在同一个事务中多次读取同一行数据时结果始终一致。避免了脏读和不可重复读问题。但依然可能存在幻读在相同的查询条件下不同的事务在不同时间点执行查询操作时可能会看到不同数量的行从而产生幻像的错觉问题。 串行化Serializable 最高的隔离级别通过确保事务串行执行来避免脏读、不可重复读和幻读问题。确保所有事务的并发执行不会导致数据不一致。在 MySQL 中可以通过设置事务的隔离级别来控制事务的隔离程度从而灵活地平衡并发性能和数据的一致性。开发者可以根据实际需求选择合适的隔离级别来确保数据操作的正确性和安全性。[]4、Mysql其他问题4.1 mysql中的null和空值有什么不一样1空值是不占空间的null值占用空间。两者就像空值是真空状态的杯子而null值是装满空气的杯子。2查寻上null 值是用is null/is not null来查询而空值( ’ ’ )则可以用 !等。 在使用聚合函数count时会过滤掉null而不会过滤掉 ’ ’ 值。在实际开发中没有特定需求可以直接使用空值4.2 mysql主从数据库延时的原因MySQL主从数据库延时可能有多种原因以下是一些常见的原因网络延迟主从数据库之间的网络连接如果不稳定或者网络质量差会导致数据同步的延迟。 主从数据库负载主数据库的负载过高或者从数据库的性能不足都可能导致数据同步延迟。 数据量过大如果要同步的数据量过大或者有大量的写操作都会增加同步的时间。 复制方式设置不当MySQL复制方式如异步复制、半同步复制等的配置不合理也会导致延时。 主从数据库版本不兼容如果主从数据库的版本不一致或不兼容也可能导致数据同步延迟。在排查MySQL主从数据库延时问题时可以逐一检查上述可能的原因逐步定位并解决问题。4.3 mysql主从复制的过程MySQL主从复制是一种常见的数据库复制技术用于将主数据库中的数据实时同步复制到从数据库。以下是MySQL主从复制的基本过程配置主数据库首先需要在主数据库上开启二进制日志Binary Log并配置主机的唯一标识Server ID。 配置从数据库在从数据库上配置连接主数据库的信息包括主数据库的IP地址、端口号、用户名密码等。同时设置从数据库的唯一标识Server ID。 启动主从复制过程在从数据库上执行CHANGE MASTER TO命令指定主数据库的连接信息并启动从数据库与主数据库的连接。 数据传输与同步当主从数据库连接成功后主数据库会将变更写入二进制日志并通过主从复制线程将这些变更传输给从数据库从数据库接收到变更后应用于自身数据库实现数据同步。 监控与维护定期检查主从数据库的状态确保主从复制正常运行。如果发现延迟或同步失败需要及时排查并解决问题。总的来说MySQL主从复制的过程包括配置主从数据库、启动复制、数据传输与同步以及监控与维护等步骤。通过主从复制可以实现数据的备份、负载均衡以及容灾等功能。[][]四、JVM虚拟机笔者此前在其他博客上整理过不在重复链接如下[][]五、Redis面试题[]1 、缓存雪崩、缓存穿透、缓存击穿*缓存雪崩* 缓存同一时间大面积失效大量请求打到数据库上数据库承受不住崩掉解决方案过期时间设置成随机、缓存预热系统出初启动先存数据到缓存里*缓存穿透* 数据库和redis中都没有数据导致大量数据查询数据库导致数据库崩掉可以将不存在的请求key的value 设置成一个字符串返回这样就避免了黑君攻击到数据库。解决方案 接口层进行校验id0的直接拒绝、采用布隆过滤器*缓存击穿* redis的一个key失效请求全部打到数据库缓存没有数据库有解决方案 热点数据永不过期设置成空字符串返回[]2、 如何保证数据库和Redis的数据一致性当我们遇到这个问题时要考虑是先删缓存还是先写数据库。延时双删 先删redis缓存数据再更新数据库然后再删redis缓存,这样就避免了删除redis和更新数据库这期间其他的线程读不到redis里的值去读数据库里的旧数据。将操作可串行化先写在读就可以了1先删缓存将更新数据库操作放到一个有序队列中2从缓存中查不到的查询操作都进入有序队列MQ问题大量读请求积压-------- 将队列水平拆分[]3、Redis的数据结构及使用场景String :字符串 ----------原子计数器List 列表 ---------微博、微信等消息流数据Set 无序集合 ---------好友推荐Zset 有序集合 -----------排行榜Hash 哈希表 ----------适合存储对象----------------------------------前五种为常见后四种为面试加分项-------------------------------------------bitmap:布隆过滤器GeoHash:坐标存储坐标的基于Zset的score进行排序就可以得到坐标附近的值HyperLoglog: 统计不重复数据用于大数据基础使用Streams:内存版的Kafka消息的订阅发布由于篇幅限制笔记无法全部为大家展示出来就以截图主要内容的形式让大家参考啦需要完整版的小伙伴可以点击https://github.com/encode-studio-fe-coder/natural_traffic/wiki/scan_material13获取文章中的文档和资料

更多文章