网易一面总结

本文深入探讨了接口与抽象类的区别,强调了进程与线程在操作系统中的角色,以及TCP与UDP在网络通信中的不同特性。同时,介绍了JVM的内存区域划分,包括程序计数器、虚拟机栈、本地方法栈、堆和方法区。此外,还提供了求解数组子数组最大和的算法及寻找特定位置数字的方法。

先是自我介绍,期间面试官给我的感觉很好

接口和抽象类的区别:

抽象类:可以有构造方法,可以有普通成员变量,可以有非抽象方法,抽象方法修饰符类型可以是public、protected、default,可以有静态方法,也可以有静态成员变量。

接口:不可以有构造方法,没有普通成员变量,不可以有非抽象方法,抽象方法修饰符必须是public,默认是public abstract,不可以包含静态方法,可以有静态成员变量。

一个类可以实现多个接口,但是只能继承一个抽象类。

接口是对动作的抽象(has-a),抽象类是对根源的抽象(is-a)。

进程与线程的区别:

进程是操作系统资源分配的基本单位,而线程是处理器任务调度和执行的基本单位,每个进程都有独立的代码和数据空间(程序上下文),程序之间的切换会有较大的开销;线程可以看做轻量级的进程,同一类线程共享代码和数据空间,每个线程都有自己独立的运行栈和PC(程序计数器),线程之间切换的开销小。如果一个进程内有多个线程,则执行过程不是一条线的,而是多条线(线程)共同完成的;线程是进程的一部分,所以线程也被称为轻权进程或者轻量级进程。同一进程的线程共享本进程的地址空间和资源,而进程之间的地址空间和资源是相互独立的。一个进程崩溃后,在保护模式下不会对其他进程产生影响,但是一个线程崩溃整个进程都死掉。所以多进程要比多线程健壮。每个独立的进程有程序运行的入口、顺序执行序列和程序出口。但是线程不能独立执行,必须依存在应用程序中,由应用程序提供多个线程执行控制,两者均可并发执行。

tcp/udp:
1、 TCP面向连接 (如打电话要先拨号建立连接); UDP是无连接 的,即发送数据之前不需要建立连接,TCP提供可靠的服务。也就是说,通过TCP连接传送的数据,无差错,不丢失,不重复,且按序到达;UDP尽最大努力交付,即不保证可靠交付,Tcp通过校验和,重传控制,序号标识,滑动窗口、确认应答实现可靠传输。如丢包时的重发控制,还可以对次序乱掉的分包进行顺序控制。

2、UDP具有较好的实时性,工作效率比TCP高,适用于对高速传输和实时性有较高的通信或广播通信。每一条TCP连接只能是点到点的;UDP支持一对一,一对多,多对一和多对多的交互通。TCP对系统资源要求较多,UDP对系统资源要求较少。

TCP三次握手四次挥手:


 

 为什么三次握手:

        防止重复连接引起连接混乱的问题,同步初始化序列化来保证稳定性。

数据库MySQL默认存储引擎InnoDB,默认隔离级别 可重复读

数据库隔离级别:

读未提交RUread-uncommitted:在RU级别中,事务读到的所有数据都是最新的数据,可能是事务提交后的数据,也可能是事务执行中的数据(可能会被回滚)。当隔离级别为RU时:所有的读不加锁,读到的数据都是最新的数据,性能最好。所有的写加行级锁,写完释放。

读已提交RCread-committed:使用MVCC技术,在每一行加入隐藏的字段(DB_TRX_ID:修改该行的最后一个事务的idDB_ROLL_PTR:指向当前行的undo log日志,DB_ROW_ID:行标识,DELETE_BIT:删除标志),它实现了不加锁的读操作。当隔离级别为RC时:写操作:加行级锁。事务开始后,会在UNDO日志中写入修改记录,数据行中的隐藏列DATA_POLL_PTR存储指向该行的UNDO记录的指针。读操作:不加锁。在读取时,如果该行被其它事务锁定,则顺着隐藏列DATA_POLL_PTR指针,找到上一个有效的历史记录(有效的记录:该记录对当前事务可见,且DELETE_BIT=0)。

可重复读RRrepeatable-read:当隔离级别为RR时:写操作:加行级锁。事务开始后,会在UNDO日志中写入修改记录,数据行中的隐藏列DATA_POLL_PTR存储指向该行的UNDO记录的指针。读操作:不加锁。在读取时,如果该行被其它事务锁定,则顺着隐藏列DATA_POLL_PTR指针,找到上一个有效的历史记录(有效的记录:该记录对当前事务可见,且DELETE_BIT=0)。

可串行化serializable读写都会加锁。

JVM五大内存区域介绍:

 

1、程序计数器

  程序计数器是一块很小的内存空间,它是线程私有的,可以认作为当前线程的行号指示器。那么计数器记录虚拟机字节码指令的地址。如果为native【底层方法】,那么计数器为空。 这块内存区域是虚拟机规范中唯一没有OutOfMemoryError的区域。

2、Java栈(虚拟机栈)

栈描述的是Java方法执行的内存模型。每个方法被执行的时候都会创建一个栈帧用于存储局部变量表,操作栈,动态链接,方法出口等信息。每一个方法被调用的过程就对应一个栈帧在虚拟机栈中从入栈到出栈的过程。平时说的栈一般指局部变量表部分。局部变量表所需要的内存空间在编译期完成分配,当进入一个方法时,这个方法在栈中需要分配多大的局部变量空间是完全确定的,在方法运行期间不会改变局部变量表大小。

Java虚拟机栈可能出现两种类型的异常:

  1. 线程请求的栈深度大于虚拟机允许的栈深度,将抛出StackOverflowError。
  2. 虚拟机栈空间可以动态扩展,当动态扩展是无法申请到足够的空间时,抛出OutOfMemory异常

3、本地方法栈

本地方法栈是与虚拟机栈发挥的作用十分相似,区别是虚拟机栈执行的是Java方法(也就是字节码)服务,而本地方法栈则为虚拟机使用到的native方法服务,可能底层调用的c或者c++,我们打开jdk安装目录可以看到也有很多用c编写的文件,可能就是native方法所调用的c代码。

4、堆

堆是java虚拟机管理内存最大的一块内存区域,因为堆存放的对象是线程共享的,所以多线程的时候也需要同步机制。java虚拟机规范对这块的描述是:所有对象实例及数组都要在堆上分配内存,但随着JIT编译器的发展和逃逸分析技术的成熟,这个说法也不是那么绝对,但是大多数情况都是这样的。即时编译器:可以把把Java的字节码,包括需要被解释的指令的程序)转换成可以直接发送给处理器的指令的程序)逃逸分析:通过逃逸分析来决定某些实例或者变量是否要在堆中进行分配,如果开启了逃逸分析,即可将这些变量直接在栈上进行分配,而非堆上进行分配。这些变量的指针可以被全局所引用,或者其其它线程所引用。堆是所有线程共享的,它的目的是存放对象实例。同时它也是GC所管理的主要区域,因此常被称为GC堆,又由于现在收集器常使用分代算法,Java堆中还可以细分为新生代和老年代。根据虚拟机规范,Java堆可以存在物理上不连续的内存空间,就像磁盘空间只要逻辑是连续的即可。它的内存大小可以设为固定大小,也可以扩展。当前主流的虚拟机如HotPot都能按扩展实现(通过设置 -Xmx和-Xms),如果堆中没有内存内存完成实例分配,而且堆无法扩展将报OOM错误(OutOfMemoryError)

5、方法区

方法区同堆一样,是所有线程共享的内存区域,为了区分堆,又被称为非堆。方法区用于存储已被虚拟机加载的类信息、常量、静态变量,如static修饰的变量加载类的时候就被加载到方法区中。在老版jdk,方法区也被称为永久代。不过自从JDK7之后,Hotspot虚拟机便将运行时常量池从永久代移除了。

手撕代码:

输入一个整型数组,数组中的一个或连续多个整数组成一个子数组。求所有子数组的和的最大值。

class Solution {

    public int maxSubArray(int[] nums) {

        int prev = 0;

        int maxAns = nums[0];

        for(int i=0;i<nums.length;i++){

            prev = Math.max(prev+nums[i],nums[i]);

            maxAns = Math.max(prev,maxAns);

        }

        return maxAns;

    }

}

给你一个整数n,请你在无限的整数序列找到并返回第n位

class Solution {
public:
    int findNthDigit(int n) {
        long long arr[10];//打表,将10^10次方以内的位数界限打出来
        for(int i=0;i<10;i++)
        {
            if(i!=0)
                arr[i] = (pow(10,i+1)-pow(10,i))*(i+1)+arr[i-1];
            else
                arr[i] = 9;
        }
        //确定位数
        int num1=0;
        for(int i=0;i<10;i++)
        {
            if(n<=arr[i])
            {
                num1=i;
                break;
            }
        }

        long long num2=0;
        if(num1==0)
            num2 = 0;
        else
            num2 = arr[num1-1];
        
        long long num3 = (n-num2-1)%(num1+1);
        
        long long num4 = (n-num2-1)/(num1+1);
        
        long long num5=pow(10,num1)+num4;
        
        string str = to_string(num5);
        
        return str[num3]-'0';
    }
};

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值