Java模拟面试-1

Java模拟面试-1

  • 简述一下操作系统中的缺页中断
  • 说一说你对volatile关键字的理解
  • 内存泄漏的问题如何解决
  • Redis有哪些数据类型
  • 算法题

简述一下操作系统中的缺页中断

缺页中断就是系统要访问的页不在内存中,需要操作系统将访问的页加载到内存中才能进行访问

说一说你对volatile关键字的理解

volatile用于保证内存的可见性,可以将其看做是轻量级的锁,它具有如下的内存语义:

· 写内存语义:当写一个volatile变量时,JMM会把该线程本地内存中的共享变量的值刷新到主内存中。

· 读内存语义:当读一个volatile变量时,JMM会把该线程本地内存置为无效,使其从主内存中读取共享变量。
其中,JMM是指Java内存模型,而本地内存只是JMM的一个抽象概念,它涵盖了缓存、写缓冲区、寄存器以及其他的硬件和编译器优化。在本文中,大家可以将其简单理解为缓存。
volatile只能保证单个变量读写的原子性,而锁则可以保证对整个临界区的代码执行具有原子性。所以,在功能上锁比volatile更强大,在可伸缩性和性能上volatile更优优势。

加分回答
volatile的底层是采用内存屏障来实现的,就是在编译器生成字节码时,会在指令序列中插入内存屏障来禁止特定类型的处理器重排序。内存屏障就是一段与平台相关的代码,Java中的内存屏障代码都在Unsafe类中定义,共包含三个方法:LoadFence()、storeFence()、fullFence()。
【延伸阅读】
可见性是指一个线程对共享变量的修改,另外一个线程能够立刻看到。可见性问题是由CPU缓存导致的,每核CPU均有各自的缓存,这些缓存均要与内存进行同步。例如,线程A要修改内存中变量X,它需要先将变量X加载到本地缓存,修改缓存后再将缓存数据刷回内存中。在线程A修改本地缓存中变量X时,线程B可能也需要读/写内存中的变量X,为了让线程A的修改对线程B感知到,就可以在变量X前加上volatile来解决。

在执行程序时,为了提高性能,编译器和处理器常常会对指令做重排序。重排序不会影响单线程的执行结果,但是在并发的情况下,可能会出现诡异的BUG。例如,instance = new Singleton(); 这行代码在执行时,会产生3条字节码指令,而这三条指令的顺序就可能会被编译器重排。CPU在执行指令时

内存泄漏的问题如何解决

内存泄漏,是指不再使用的对象仍然被引用,导致垃圾收集器无法回收它们的内存。由于不再使用的对象仍然无法清理,甚至这种情况可能会越积越多,最终导致致命的OutOfMemoryError,长生命周期的对象保持短生命周期对象的引用会导致内存泄漏。

Redis有哪些数据类型

它主要提供了5种数据类型:字符串(string)、哈希(hash)、列表(list)、集合(set)、有序集合(zset)。Redis还提供了Bitmap、HyperLogLog、Geo类型,但这些类型都是基于上述核心数据类型实现的。5.0版本中,Redis新增加了Streams数据类型,它是一个功能强大的、支持多播的、可持久化的消息队列。

  1. string可以存储字符串、数字和二进制数据,除了值可以是String以外,所有的键也可以是string,string最大可以存储大小为512M的数据。

  2. list保证数据线性有序且元素可重复,它支持lpush、blpush、rpop、brpop等操作,可以当作简单的消息队列使用,一个list最多可以存储2^32-1个元素。

  3. hash的值本身也是一个键值对结构,最多能存储2^32-1个元素。

  4. set是无序不可重复的,它支持多个set求交集、并集、差集,适合实现共同关注之类的需求,一个set最多可以存储2^32-1个元素。

  5. zset是有序不可重复的,它通过给每个元素设置一个分数来作为排序的依据,一个zset最多可以存储2^32-1个元素。

算法题

定义重复字符串是由两个相同的字符串首尾拼接而成。例如:“abcabc” 是一个长度为 6 的重复字符串,因为它由两个 “abc” 串拼接而成;“abcba” 不是重复字符串,因为它不能由两个相同的字符串拼接而成。

给定一个字符串,请返回其最长重复子串的长度。

若不存在任何重复字符子串,则返回 0。

本题中子串的定义是字符串中一段连续的区间。

数据范围:字符串长度不大于 10^3,保证字符串一定由小写字母构成。
进阶:空间复杂度 ,时间复杂度

思路:
可以将两个字符串想像成两个连续的滑动窗口,并假设这个滑动窗口最大是字符串长度的一半,通过比较两个窗口的内容是否相同,不相同的时候不断从左向右平移,完了之后,还是不相同,这时候就将窗口的大小调小一点,直到找到一个相同的,这个时候窗口的长度×2就是最大字符串的大小

    public int solve (String a) {
        // write code here
        if(a.length() <= 1) {
            return 0;
        }
        char[] chars = a.toCharArray();
        // 控制窗口大小
        for(int window = a.length() / 2;window > 0;window--) {
            int last = window*2 -1;
            // 移动窗口
            int start = 0;
            while(last <= a.length()-1) {
                last++;
                // 遍历数据
                boolean flag = true;
                for(int i = start;i < start + window;i++) {
                    if(chars[i] != chars[i+window]) {
                        // 结束当前内层的for循环,进行下一次循环
                        flag = false;
                        continue;
                    }
                }
                start++;
                if(flag == true) {
                    return window * 2;
                }
            }
        }
        return 0;
    }

你可能感兴趣的:(面试实战,面试,java,jvm)