java基础题

1、一个静态方法内调用一个非静态成员为什么是非法的?

静态方法数据类本身,在类加载时分配到内存。

非静态成员属于对象,只有在类被实例化时才能被加载到内存,因此当静态方内调用非静态成员时,非静态成员可能不存在,加载一个不存在的东西肯定会报错

2、为什么两个对象有相同的hashCode,两个对象不一定相等?

==:如果是数值,则进行值比较,如果是对象则判断两个对象jvm中的地址

equals底层实现

从中可以看出,当比较值为字符串时,则直接进行字符串比较,原因为:String 是使用比较频繁的对象类,所以JVM为了优化性能和减少开销,在内存中单独开出一块区域,即字符串常量池,需要使用时,先看字符串常量池中是否存在,如果不存在,则初始化,把字符串放入常量池,如果存在则直接使用。

3、线程有哪些基本状态:

开始:线程开始创建还未启动

运行:此时运行为两部分,running和ready, running标识线程已经启动,ready标识线程等待CPU分配时间

等待:分为无限期等待和有限期等待,无限期等待是无timeout时间的wait,没有timeout的Thread.join(),需要外部显示唤醒才能等待结束,有限期等待为Thread.sleep(),带timeout时间的Object.wai()和带timeout的Thread.join(),当到达一定时间后会自动唤醒。

阻塞:如果线程被阻塞,则阻塞和等待区别为:阻塞需要获取一个排它锁,这个将在其他线程释放这个锁开始,等待则为等待一段时间或唤醒动作的发生。

结束:已经终止的线程状态,当前线程已结束。

4、什么是自动拆箱?什么是自动封箱?

自动拆封箱是基本数据类型整数类型(int,byte,short,long)、字符类型(char)、布尔类型(boolean)、浮点类型(double,float)包装类转化

5、java常见IO阻塞模型

为了保护数据安全,将内存分为两部分:

1、用户空间

2、内存空间

获取数据的过程也可以分为两步:

1、用户空间从内存空间中申请,等在内存空间获取数据

2、当内存空间获取到数据后,从内存空间拷贝到用户空间

几种io模型:

1、阻塞io

常规io模型,用户线程获取数据时,阻塞等待内存空间获取数据,直到存空间数据获取完毕,内存空间将数据拷贝到用户空间,阻塞结束,用户线程进行数据处理。

2、非阻塞io

设置socket为NIO(NONBLOCK),用户线程从内存空间获取数据发起io请求后立即返回,然后不断的发起io请求直到内存空间获取到数据,将数据从内存空间拷贝到用户空间,用户线程读取完毕。

3、多路复用io

用户将需要监控的socket注册到select中,然后阻塞等待select返回,当数据到达内存空间后,socket被激活,select返回,用户线程发起IO请求,读取完成后进行后续操作。

优点:用户可以注册多个socket到select,然后不断读取select状态,从而实现一个线程管理多个IO请求的目的,而在同步阻塞模型中,必须通过多线程才能实现。

虽然上述模式允许单个线程内处理多个 IO,但是每个IO还是阻塞的(select函数阻塞),平均时长甚至比同步阻塞IO还要长,但是用户可以只注册自己感兴趣的IO请求,当数据准备完毕后,socket被激活,用户才进行数据读取,从而提高CPU利用率。

多路复用IO基于Reactor设计模式实现了这一机制

EventHandler抽象类表示IO文件事件处理器,他包含文件句柄handler和对文件处理事件操作handler_event()。继承EventHandler可以对文件事件处理进行定制。Reactor类则对EventHandler进行管理(注册、删除),使用handler_events()进行事件循环,通过不断轮询多路分离器的多路分离函数select,当某一个文件句柄被激活,select就返回,handler_events就会调用与句柄相关的handler_event进行后续文件处理。

总之:通过Reactor方式,可以将轮询IO状态的工作统一交给handler_events()进行处理,当用户线程注册时间处理器后可以进行其他操作,Reactor线程则不断调用select函数查询socket状态,当有socket被激活后,则通知用户线程,执行handler_event时间处理。

6、CPU上下文切换

什么是cpu上下文

任务执行过程中,CPU需要知道从哪里加载,从哪里运行,所以需要系统分配CPU寄存器(CPU内置一个空间极小,运行速度极快的内存)和程序计数器(用来存储当前指令位置或者下一次指令位置),他们是CPU运行任务前,所依赖的环境,也称为CPU上下文。

CPU上下文切换的几种方式

--进程上下文切换

Linux根据特权等级,将进行运行空间分为用户空间和内核空间,进程在两个空间运行分别叫做用户态和内存态,用户态和内存态跳转是通过系统调用完成的。

系统调用:CPU寄存器首先保存用户态的指令,为了在内存态运行任务,需要刷新CPU寄存器为内存态指令,然后跳转到内存态运行任务,任务运行完毕后,CPU寄存器恢复用户态指令,然后跳回到用户空间,进程继续运行。所以系统调用时发生了两次CPU上下文切换,需要注意的是系统调用不会涉及到虚拟内存等用户空间的资源,也不会切换进程,所以系统调用和进程切换是有区别的:

进程切换是指从一个进程切换到另一个进程

系统调用是在同一个进程中执行的

--系统调用和进程上下文切换的区别:

进程是在内核中管理和切换的,进程的切换只能在内核中完成,进程的切换不仅包含用户空间的虚拟内存、栈、全局变量等资源,还包含内核堆栈,寄存器等内核资源。

进程上下文切换比系统调用多了一步,在保存内存态状态和CPU寄存器之前,首先需要保存虚拟内存,栈等,当内核态进程切换完成之后,还需要刷新虚拟内存和用户栈等

2、线程上下文切换

线程是调度的基本单位,进程是资源拥有的基本单位,所谓内核中的任务调度,实际调度对象是线程,进程只是提供虚拟内存、栈、全局变量等资源。所以线程上下文切换分为两种情况:

--不同进程之间的线程切换,等同于进程之间的切换

--相同线程之间的切换,线程共享的虚拟内存、全局变量等资源无需切换,只是切换线程私有的栈和寄存器等。

3、中断上下文切换

为了快速响应硬件,中断程序需要中断当前正常运行的进程,来运行中断程序,在中断进程前,首先保存被中断进程状态,当中断程序执行完毕后,被打断进程恢复继续执行。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值