字节java后端广告2025.03.19 一面过 二面挂

系列博客目录



1.流程

  1. 自我介绍

  2. 项目难点:在项目中,数据报表导出时遇到了性能瓶颈,主要是在导出大数据量时,使用 Apache POI导出的方式导致 CPU 占用过高 和 内存溢出(OOM) 的问题,甚至出现了程序假死的现象。为了优化这个问题,我进行了以下改进:首先,我将 Apache POI替换为EasyExcel,因为 EasyExcel 支持流式操作,可以逐行写入,避免了将所有数据加载到内存中,从而有效降低了内存消耗并解决了 OOM 问题。其次,我引入了 多线程,将数据导出任务分成多个线程并行处理,每个线程处理不同数据块,从而利用多核 CPU 提升了导出效率。最终,我使用了 JMeter和 JVisualVM进行性能测试,优化后,导出速度提升了 30%,并且 内存占用减少了 40%,系统性能大幅提高,避免了导出大数据时的卡顿和高负载问题。这一优化措施不仅提升了数据导出的效率,还提高了系统的稳定性

  3. 项目难点还没说完,就被打断被问到 多线程怎么做到减少内存的使用。应该是前面口误,把“我引入了 多线程,将数据导出任务分成多个线程并行处理,每个线程处理不同数据块,从而利用多核 CPU 提升了导出效率”说成了多线程可以减少内存使用了。

  4. 多线程在导出文件的过程中有没有起到优化的过程。

  5. 问到项目还有没有什么难点,我又说了:“使用Redis 和 Caffeine 实现多级缓存,目的是结合二者的优势来提高系统性能。首先,当用户请求数据时,系统会先检查本地缓存(Caffeine),如果命中则直接返回。如果本地缓存未命中,则查询 Redis,如果 Redis 中也没有数据,再从数据库中查询。这样,频繁访问的数据可以保存在本地缓存中,减少 Redis 的负载,提高查询效率。通过这种方式,系统能够在保证高性能的同时,减轻 Redis 和数据库的压力,提升整体的响应速度。”

  6. 又问了一下项目还有什么难点或者亮点,我说没了。。。准备不够充分

  7. redis和本地缓存如何保持一致性?要保持本地缓存和Redis一致,可以采用以下几种常见方法:
    缓存更新策略:
    • 定时更新:设置一个固定的时间间隔,定期从Redis中获取最新数据来更新本地缓存。这种方式实现简单,但可能存在数据更新不及时的问题。
    • 事件驱动更新:当Redis中的数据发生变化时,通过消息队列等方式发送通知,本地缓存接收到通知后立即进行更新。这样能保证数据的实时一致性,但需要额外的消息机制支持。
    数据同步机制

  8. 自己在编码是可不可以创建一个com.byteDance.string类,在想要使用它的时候能不能拿到它。我回答不可以因为,我如果编写,可能会与大佬们已经创建好的类冲突。他又提问先不说这个问题,为什么有些包中的类他有很多相同的名字,我们是怎么知道调用哪个的呢,比如Jackson有很多包中的类名都叫Jackson

  9. Redis中ZSet你知道吗

  10. 底层用的跳表,为什么用跳表 不用红黑树

  11. 跳表是什么

  12. volatile关键字可以保证线程安全吗

  13. SPI

  14. 在使用Spring是,interceptor和filter的区别是什么? 回答的时候提到了MVC

  15. SpringMVC的执行流程是什么

  16. 查找数据库中的一行数据很慢,是为什么

  17. 在进行DML和DDL操作的时候,会影响上面的查询,导致他慢吗

  18. Mysql我想存IP地址,应该如何存?在MySQL中存储IP地址,通常有以下两种方式:

    使用字符串类型(VARCHAR)

    • 优点:直观,易于理解和使用,可直接存储IP地址的字符串形式,如’192.168.1.1’,对IP地址的格式没有严格限制,存储和查询操作相对简单。

    使用整数类型(INT)

    • 优点:占用空间小,存储和查询效率高,可通过将IP地址转换为整数进行存储和计算。

  19. 为什么要进行转换(上面提到的)?将IP地址转换为整数存储主要有以下原因:

    • 节省存储空间:IPv4地址用点分十进制表示,如192.168.1.1,需15个字符存储。而转换为32位整数,只需4个字节,能节省存储空间,在存储大量IP地址时优势明显。IPv6地址用VARBINARY(16)存储,相比字符串形式也更省空间。

    • 提高查询效率:整数在数据库中比较和排序的效率比字符串高。以整数形式存储IP地址,在进行范围查询、比较操作时,数据库可直接对整数进行计算和比较,无需像处理字符串那样逐个字符比较,能显著提高查询性能。

    • 便于计算:将IP地址转换为整数后,便于进行一些与IP地址相关的计算,如判断IP地址是否在某个网段内等。通过对整数进行位运算,可以快速实现这些功能,提高数据处理的效率。

  20. 大key如何删除
    在Redis中,删除大key(指存储大量数据的key)是一个需要谨慎处理的问题,因为直接删除这些大key可能会导致阻塞,影响Redis的性能。以下是一些常见的策略和方法,用于删除Redis中的大key:

1. 使用 UNLINK 命令

  • UNLINK 命令是删除大key的推荐方式。与 DEL 命令不同,UNLINK 是异步执行的,它会将删除操作移到后台执行,避免阻塞Redis主线程。这样,删除大key时不会影响到其他命令的执行。
  • 优点:减少阻塞,删除过程异步进行。
  • 示例
    UNLINK large_key
    

2. 使用 DEL 命令(需要谨慎)

  • DEL 命令是同步删除命令,当删除一个大key时,Redis会阻塞直到该操作完成。删除大key时,这个过程可能会持续几秒或更长时间,导致系统性能下降,甚至出现“请求超时”或“服务不可用”的问题。
  • 优点:删除简单。
  • 缺点:可能会导致长时间的阻塞,影响系统的响应速度。

如果必须使用 DEL 命令删除大key,可以选择在低流量的时段进行,或者采用其他优化方法,如分片删除(见下文)。

3. 分步删除(渐进式删除)

  • 对于大集合(如大列表、哈希表或集合),可以考虑逐步删除集合中的元素,而不是一次性删除整个大key。使用 Redis 的 SCAN 命令可以遍历大key的所有元素,然后分批次地删除。
  • 示例(针对大集合):
    SCAN 0 MATCH large_key:* COUNT 1000
    
    这里使用 SCAN 命令来扫描并逐步删除集合中的元素,避免一次性删除时带来的阻塞。
  1. Redis中Zset
  2. Zset为什么使用跳表
  3. 跳表是什么
  4. static和final属性都是什么时候赋值
  5. 多线程循环打印123
    题目描述:启动3个线程,线程1无限循环打印1、线程2无限循环打印2、线程3天限循环打印3,要求按123123.顺序循环打印
public class OrderedPrinting {
    // 共享锁对象
    private static final Object lock = new Object();
    // 当前应该打印的数字
    private static int currentNumber = 1;

    public static void main(String[] args) {
        // 创建并启动三个线程
        Thread thread1 = new Thread(new Printer(1));
        Thread thread2 = new Thread(new Printer(2));
        Thread thread3 = new Thread(new Printer(3));

        thread1.start();
        thread2.start();
        thread3.start();
    }

    static class Printer implements Runnable {
        private final int number;

        public Printer(int number) {
            this.number = number;
        }

        @Override
        public void run() {
            while (true) {
                synchronized (lock) {
                    // 如果当前线程不是应该打印的线程,则等待
                    while (number != currentNumber) {
                        try {
                            lock.wait();
                        } catch (InterruptedException e) {
                            Thread.currentThread().interrupt();
                            return;
                        }
                    }

                    // 打印数字
                    System.out.print(number);

                    // 更新下一个应该打印的数字
                    currentNumber = currentNumber % 3 + 1;

                    // 唤醒所有等待的线程
                    lock.notifyAll();
                }
            }
        }
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值