纯⼲货分享!2020阿⾥java岗笔试⾯试题总结(附答案)
前⾔
2020⾦九银⼗马上结束,现为⼤家整理了这次⾦九银⼗⾯试阿⾥的⾯试题总结,都是我从朋友那拿到的⾯试真题,话不多说,满满的⼲货分享给⼤家!
int a=10是原⼦操作吗?
是的。
注意点:
i++(或++i)是⾮原⼦操作,i++是⼀个多步操作,⽽且是可以被中断的。i++可以被分割成3步,第⼀步读取i的值,第⼆步计算i+1;第三部将最终值赋值给i。
* int a = b;不是原⼦操作。从语法的级别来看,这是也是⼀条语句,是原⼦的;但是从实际执⾏的⼆进制指令来看,由于现代计算机CPU架构体系的限制,数据不可以直接从内存搬运到另外⼀块内存,必须借助寄存器中断,这条语句⼀般对应两条计算机指令,即将变量b的值搬运到某个寄存器(如eax)中,再从该寄存器搬运到变量a的内存地址:
mov eax, dword ptr [b]
mov dword ptr [a], eax
既然是两条指令,那么多个线程在执⾏这两条指令时,某个线程可能会在第⼀条指令执⾏完毕后被剥夺CPU时间⽚,切换到另外⼀个线程⽽产⽣不确定的情况。
innodb⽀持全⽂索引吗?
5.6版本之后InnoDB存储引擎开始⽀持全⽂索引,5.7版本之后通过使⽤ngram插件开始⽀持中⽂。之前仅⽀持英⽂,因为是通过空格作为分词的分隔符,对于中⽂来说是不合适的。MySQL允许在char、varchar、text类型上建⽴全⽂索引。
innodb⽀持表锁吗?
⽀持,补充:普通的增删改是表锁,加⼊索引的增删改是⾏锁,执⾏查询时不加任何锁的。
HTTP短连接怎么变成长连接。
在header中加⼊ --Connection:keep-alive。
调⽤yeild()会阻塞吗?
阻塞指的是暂停⼀个线程的执⾏以等待某个条件发⽣(如某资源就绪)。
yield() ⽅法:yield() 使得线程放弃当前分得的 CPU 时间,但是不使线程阻塞,即线程仍处于可执⾏状态,随时可能再次分得 CPU 时间。调⽤ yield() 的效果等价于调度程序认为该线程已执⾏了⾜够的时间从⽽转到另⼀个线程。yield()只是使当前线程重新回到可执⾏状态,所以执⾏yield()的线程有可能在进⼊到可执⾏状态后马上⼜被执⾏。sleep()可使优先级低的线程得到执⾏的机会,当然也可以让同优先级和⾼优先级的线程有执⾏的机会;yield()只能使同优先级的线程有执⾏的机会。
虚拟机栈是线程共享的吗?
不是。
JVM初始运⾏的时候都会分配好 Method Area(⽅法区)和Heap(堆),⽽JVM 每遇到⼀个线程,就为其分配⼀个 Program Counter Register(程序计数器) , VM Stack(虚拟机栈)和Native Method Stack (本地⽅法栈),当线程终⽌时,三者(虚拟机栈,本地⽅法栈和程序计数器)所占⽤的内存空间也会被释放掉。这也是为什么我把内存区域分为线程共享和⾮线程共享的原因,⾮线程共享的那三个区域的⽣命周期与所属线程相同,⽽线程共享的区域与JAVA程序运⾏的⽣命周期相同,所以这也
是系统垃圾回收的场所只发⽣在线程共享的区域(实际上对⼤部分虚拟机来说只发⽣在Heap上)的原因。
栈区:
每个线程包含⼀个栈区,栈中只保存基础数据类型的值(⽐如int i=1中1就是基础类型的对象)和对象的引⽤以及基础数据的引⽤每个栈中的数据(基础数据类型和对象引⽤)都是私有的,其他栈不能访问。onclick事件更改fragment
栈分为3个部分:基本类型变量区、执⾏环境上下⽂、操作指令区(存放操作指令)。
堆区:
存储的全部是对象,每个对象都包含⼀个与之对应的class的信息。(class的⽬的是得到操作指令)
jvm只有⼀个堆区(heap)被所有线程共享,堆中不存放基本类型和对象引⽤,只存放对象本⾝。
⽅法区:
⼜叫静态区,跟堆⼀样,被所有的线程共享。⽅法区包含所有的class和static变量。
⽅法区中包含的都是在整个程序中永远唯⼀的元素,如class,static变量。(两者区别为堆区存放new
出来的对象信息,⽅法区存放本⾝就具有的类信息)
常量存放在JVM的那个区域?
⽅法区: ⼜叫静态区,跟堆⼀样,被所有的线程共享。它⽤于存储已经被虚拟机加载的类信息、常量、静态变量、即时编译器编译后的代码等数据。
window.postMessage() ⽅法可以安全地实现跨源通信。通常,对于两个不同页⾯的脚本,只有当执⾏它们的页⾯位于具有相同的协议(通常为https),端⼝号(443为https的默认值),以及主机 (两个页⾯的模数 Document.domain设置为相同的值) 时,这两个脚本才能相互通信。window.postMessage() ⽅法提供了⼀种受控机制来规避此限制,只要正确的使⽤,这种⽅法就很安全。
所有的对象都分配到堆中吗?
答:不⼀定。
CopyOnWriteArrayList是线程安全的吗?
CopyOnWriteArrayList使⽤了⼀种叫写时复制的⽅法,当有新元素添加到CopyOnWriteArrayList时,先从原有的数组中拷贝⼀份出来,然后在新的数组做写操作,写完之后,再将原来的数组引⽤指向到
新数组。创建新数组,并往新数组中加⼊⼀个新元素,这个时候,array这个引⽤仍然是指向原数组的。当元素在新数组添加成功后,将array这个引⽤指向新数组。
CopyOnWriteArrayList的整个add操作都是在锁的保护下进⾏的。这样做是为了避免在多线程并发add的时候,复制出多个副本出来,把数据搞乱了,导致最终的数组数据不是我们期望的。
public boolean add(E e) {
//1、先加锁
final ReentrantLock lock = this.lock;
lock.lock();
try {
Object[] elements = getArray();
int len = elements.length;
//2、拷贝数组
Object[] newElements = pyOf(elements, len + 1);
//3、将元素加⼊到新数组中
newElements[len] = e;
//4、将array引⽤指向到新数组
setArray(newElements);
return true;
} finally {
//5、解锁
lock.unlock();spring ioc容器初始化过程
}
}
由于所有的写操作都是在新数组进⾏的,这个时候如果有线程并发的写,则通过锁来控制,如果有线程并发的读,则分⼏种情况:
如果写操作未完成,那么直接读取原数组的数据;
java常见笔试题如果写操作完成,但是引⽤还未指向新数组,那么也是读取原数组数据;
如果写操作完成,并且引⽤已经指向了新的数组,那么直接从新数组中读取数据。
可见,CopyOnWriteArrayList的读操作是可以不⽤加锁的。
CopyOnWriteArrayList 有⼏个缺点:
由于写操作的时候,需要拷贝数组,会消耗内存,
如果原数组的内容⽐较多的情况下,可能导致young gc或者full gc
不能⽤于实时读的场景,像拷贝数组、新增元素都需要时间,
所以调⽤⼀个set操作后,读取到数据可能还是旧的,
php怎样执行虽然CopyOnWriteArrayList 能做到最终⼀致性,但是还是没法满⾜实时性要求;
CopyOnWriteArrayList 合适读多写少的场景,不过这类慎⽤
因为谁也没法保证CopyOnWriteArrayList 到底要放置多少数据,
万⼀数据稍微有点多,每次add/set都要重新复制数组,这个代价实在太⾼昂了。
在⾼性能的互联⽹应⽤中,这种操作分分钟引起故障。
CopyOnWriteArrayList透露的思想
读写分离,读和写分开
最终⼀致性
使⽤另外开辟空间的思路,来解决并发冲突
数组越界问题
⼀般来讲我们使⽤时,会⽤⼀个线程向容器中添加元素,⼀个线程来读取元素,⽽读取的操作往往更加频繁。写操作加锁保证了线程安全,读写分离保证了读操作的效率,简直完美。
如果这时候有第三个线程进⾏删除元素操作,读线程去读取容器中最后⼀个元素,读之前的时候容器⼤⼩为i,当去读的时候删除线程突然删除了⼀个元素,这个时候容器⼤⼩变为了i-1,读线程仍然去读取第i个元素,这时候就会发⽣数组越界。
测试⼀下,⾸先向CopyOnWriteArrayList⾥⾯塞10000个测试数据,启动两个线程,⼀个不断的删除元素,⼀个不断的读取容器中最后⼀个数据。
public void test(){
for(int i = 0; i<10000; i++){
list.add("string" + i);
}
new Thread(new Runnable() {
@Override
public void run() {
while (true) {
if (list.size() > 0) {
String content = (list.size() - 1);
}else {
break;
}
}
}
new Thread(new Runnable() {
@Override
public void run() {
while (true) {
if(list.size() <= 0){
break;
}
try {
Thread.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}).start();
}
Java接⼝可以多继承吗?
java类是单继承的。classB extends classA
java接⼝可以多继承。Interface3 extends Interface0, Interface1, interface……
不允许类多重继承的主要原因是,如果A同时继承B和C,⽽B和C同时有⼀个D⽅法,A如何决定该继承那⼀个呢?
但接⼝不存在这样的问题,接⼝全都是抽象⽅法继承谁都⽆所谓,所以接⼝可以继承多个接⼝。
(byte)300==(byte)100+(short)200?
答:false。
java中byte的取值范围是-128~127,发⽣上溢下溢时要模256;130>127上溢,故模256得130,仍溢出,再减256得-126,所以s=-126。300>127上溢,故模256得44,44在byte取值范围内,故s=44.
300 的⼆进制是:100101100;byte强制转换后从右往左取8位为:00101100;因为第⼋位为0所以为正数,⼜知道正数的原反补码都相同;所以00101100转换为⼗进制是:44(32+8+4)
(byte)100+(short)200,byte和short的结果会⾃动转为short不会溢出。所以(byte)100+(short)200=(short)300,⽽(byte)300的结果是44.即两者不相等。
操作系统具有进程管理,存储管理,⽂件管理和设备管理的功能,下列有关描述中,哪⼀项是不正确的? (A)
A.进程管理主要是对程序进⾏管理
B.存储管理主要管理内存资源
C.⽂件管理可以有效的⽀持对⽂件的操作,解决⽂件共享、保密和保护问题
D. 设备管理是指计算机系统中除了CPU和内存以外的所有输⼊输出设备的管理
this和super正确的是(C):
A、都可以⽤在main()⽅法中
B、都是指⼀个内存地址
C、不能⽤在main()⽅法中
D、意义相同
public static void main(String[] args),main⽅法是静态⽅法,不可以使⽤对象特有的this或super关键字。
引⽤计数法是JVM GC算法吗?
答:是。
能在try{}catch(){}finally{}结构的finally{}中再次抛出异常吗?
答:能。
Exception in thread “main” java.lang.Exception: 异常4
st.FinallyTry.f(FinallyTry.java:16)
st.FinallyTry.main(FinallyTry.java:5)
--------在finally中抛异常或者return 会掩盖之前的异常
HTTP2新特性?
答:减少头部的体积、添加请求优先级、服务器推送、多路复⽤。
索引可以将随机IO变成顺序IO吗?
答:对。
随机IO:假设我们所需要的数据是随机分散在磁盘的不同页的不同扇区中的,那么到相应的数据需要等到磁臂(寻址作⽤)旋转到指定的页,然后盘⽚寻到对应的扇区,才能到我们所需要的⼀块数据,依次进⾏此过程直到完所有数据,这个就是随机IO,读取数据速度较慢。
顺序IO:假设我们已经到了第⼀块数据,并且其他所需的数据就在这⼀块数据后边,那么就不需要
重新寻址,可以依次拿到我们所需的数据,这个就叫顺序IO。
transient修饰的变量是临时变量吗?
答:对。
⼀旦变量被transient修饰,变量将不再是对象持久化的⼀部分,该变量内容在序列化后⽆法获得访问。
transient关键字只能修饰变量,⽽不能修饰⽅法和类。注意,本地变量是不能被transient关键字修饰的。变量如果是⽤户⾃定义类变量,则该类需要实现SERIALIZABLE接⼝。
被transient关键字修饰的变量不再能被序列化,⼀个静态变量不管是否被transient修饰,均不能被序列化。
注意点:在Java中,对象的序列化可以通过实现两种接⼝来实现,若实现的是SERIALIZABLE接⼝,则所有的序列化将会⾃动进⾏,若实现的是Externalizable接⼝,则没有任何东西可以⾃动序列化,需要在writeExternal⽅法中进⾏⼿⼯指定所要序列化的变量,这与是否被transient修饰⽆关。
⾼、中、低三级调度。
通配符是什么条件格式下输入的⾼级调度:即作业调度,按照⼀定策略将选择磁盘上的程序装⼊内存,并建⽴进程。(存在与多道批处理系统中)
中级调度:即交换调度,按照⼀定策略在内外存之间进⾏数据交换。
低级调度:即CPU调度(进程调度),按照⼀定策略选择就绪进程,占⽤cpu执⾏。
其中低度调度是必须的。
下⾯那个查看80端⼝是否被占⽤?
⽅式⼀:ps -ef |grep 80
⽅式⼆:netstat -anp |grep :80
国的unicode编码⽅式三:lsof -i:80
⽅式四:netstat -tunlp |grep :80
⽅式五:netstat -an |grep :80
C++弱引⽤指针是那个?
weak_ptr也是⼀个引⽤计数型智能指针,但是它不增加对象的引⽤计数,即弱引⽤。与之相对,shared_ptr是强引⽤,只要有⼀个指向对象的shared_ptr存在,该对象就不会析构,直到指向对象的最后⼀个shared_ptr析构或reset()时才会被销毁。
利⽤weak_ptr,我们可以解决常见的空悬指针问题以及循环引⽤问题。
下⾯不属于类的构造⽅法具备的特点是( )。
A.没有返回值
B.⽤户可以通过new⾃动调⽤。
C.构造⽅法名必须和类名相同
D.⽤户可以直接调⽤
D [解析] 构造⽅法是类中的⼀种特殊⽅法,是为对象初始化操作编写的⽅法,⽤它来定义对象的初始状态。在Java语⾔中的每个类都
有构造⽅法,它也是由⽅法名、参数和⽅法体组成。构造⽅法名必须与类名相同,它没有返回值,⽤户不能直接调⽤它,只能通过new⾃动调⽤。
spx协议⼯作在哪⼀层?
SPX(Sequenced Packet Exchange protocol,顺序包交换)协议是Novell开发的⽤在NetWare中的协议,⽤来确保信息成功传送。SPX使⽤NetWare的IPX协议作为它的传递机制并在⽹络结点间提供客户服务器和层对层的交互通信。它⼯作在传输层。
TCP第四次挥⼿后为什么要等待2MSL后才断开链接?等待时间为什么是2MSL?
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论