2020金九银十立刻结束,现为你们整理了此次金九银十面试阿里的面试题总结,都是我从朋友那拿到的面试真题,话很少说,满满的干货分享给你们!java
是的。
注意点:面试
mov eax, dword ptr [b] mov dword ptr [a], eax
既然是两条指令,那么多个线程在执行这两条指令时,某个线程可能会在第一条指令执行完毕后被剥夺CPU时间片,切换到另一个线程而产生不肯定的状况。算法
5.6版本以后InnoDB存储引擎开始支持全文索引,5.7版本以后经过使用ngram插件开始支持中文。以前仅支持英文,由于是经过空格做为分词的分隔符,对于中文来讲是不合适的。MySQL容许在char、varchar、text类型上创建全文索引。后端
支持,补充:普通的增删改 是表锁,加入索引的增删改是行锁,执行查询时不加任何锁的。数组
在header中加入 --Connection:keep-alive。安全
阻塞指的是暂停一个线程的执行以等待某个条件发生(如某资源就绪)。
yield() 方法:yield() 使得线程放弃当前分得的 CPU 时间,可是不使线程阻塞,即线程仍处于可执行状态,随时可能再次分得 CPU 时间。调用 yield() 的效果等价于调度程序认为该线程已执行了足够的时间从而转到另外一个线程。yield()只是使当前线程从新回到可执行状态,因此执行yield()的线程有可能在进入到可执行状态后立刻又被执行。sleep()可以使优先级低的线程获得执行的机会,固然也可让同优先级和高优先级的线程有执行的机会;yield()只能使同优先级的线程有执行的机会。服务器
不是。网络
JVM初始运行的时候都会分配好 Method Area(方法区) 和Heap(堆) ,而JVM 每遇到一个线程,就为其分配一个 Program Counter Register(程序计数器) , VM Stack(虚拟机栈)和Native Method Stack (本地方法栈), 当线程终止时,三者(虚拟机栈,本地方法栈和程序计数器)所占用的内存空间也会被释放掉。这也是为何我把内存区域分为线程共享和非线程共享的缘由,非线程共享的那三个区域的生命周期与所属线程相同,而线程共享的区域与JAVA程序运行的生命周期相同,因此这也是系统垃圾回收的场所只发生在线程共享的区域(实际上对大部分虚拟机来讲只发生在Heap上)的缘由。多线程
方法区: 又叫静态区,跟堆同样,被全部的线程共享。它用于存储已经被虚拟机加载的类信息、常量、静态变量、即时编译器编译后的代码等数据。架构
window.postMessage() 方法能够安全地实现跨源通讯。一般,对于两个不一样页面的脚本,只有当执行它们的页面位于具备相同的协议(一般为https),端口号(443为https的默认值),以及主机 (两个页面的模数 Document.domain设置为相同的值) 时,这两个脚本才能相互通讯。window.postMessage() 方法提供了一种受控机制来规避此限制,只要正确的使用,这种方法就很安全。
答:不必定。
答:是的。
CopyOnWriteArrayList使用了一种叫写时复制的方法,当有新元素添加到CopyOnWriteArrayList时,先从原有的数组中拷贝一份出来,而后在新的数组作写操做,写完以后,再将原来的数组引用指向到新数组。建立新数组,并往新数组中加入一个新元素,这个时候,array这个引用仍然是指向原数组的。当元素在新数组添加成功后,将array这个引用指向新数组。
CopyOnWriteArrayList的整个add操做都是在锁的保护下进行的。这样作是为了不在多线程并发add的时候,复制出多个副本出来,把数据搞乱了,致使最终的数组数据不是咱们指望的。
public boolean add(E e) { //一、先加锁 final ReentrantLock lock = this.lock; lock.lock(); try { Object[] elements = getArray(); int len = elements.length; //二、拷贝数组 Object[] newElements = Arrays.copyOf(elements, len + 1); //三、将元素加入到新数组中 newElements[len] = e; //四、将array引用指向到新数组 setArray(newElements); return true; } finally { //五、解锁 lock.unlock(); } }
因为全部的写操做都是在新数组进行的,这个时候若是有线程并发的写,则经过锁来控制,若是有线程并发的读,则分几种状况:
可见,CopyOnWriteArrayList的读操做是能够不用加锁的。
CopyOnWriteArrayList 有几个缺点:
因为写操做的时候,须要拷贝数组,会消耗内存,
若是原数组的内容比较多的状况下,可能致使young gc或者full gc
不能用于实时读的场景,像拷贝数组、新增元素都须要时间,
因此调用一个set操做后,读取到数据可能仍是旧的,
虽然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.get(list.size() - 1); }else { break; } } } }).start(); new Thread(new Runnable() { @Override public void run() { while (true) { if(list.size() <= 0){ break; } list.remove(0); try { Thread.sleep(10); } catch (InterruptedException e) { e.printStackTrace(); } } } }).start(); }
java类是单继承的。classB extends classA
java接口能够多继承。Interface3 extends Interface0, Interface1, interface……
不容许类多重继承的主要缘由是,若是A同时继承B和C,而B和C同时有一个D方法,A如何决定该继承那一个呢?
但接口不存在这样的问题,接口全都是抽象方法继承谁都无所谓,因此接口能够继承多个接口。
答: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.进程管理主要是对程序进行管理
B.存储管理主要管理内存资源
C.文件管理能够有效的支持对文件的操做,解决文件共享、保密和保护问题
D. 设备管理是指计算机系统中除了CPU和内存之外的全部输入输出设备的管理
A、均可以用在main()方法中 B、都是指一个内存地址
C、不能用在main()方法中 D、意义相同
public static void main(String[] args),main方法是静态方法,不可使用对象特有的this或super关键字。
答:是。
答:能。
Exception in thread “main” java.lang.Exception: 异常4
at com.test.FinallyTry.f(FinallyTry.java:16)
at com.test.FinallyTry.main(FinallyTry.java:5)
--------在finally中抛异常或者return 会掩盖以前的异常
答:减小头部的体积、添加请求优先级、服务器推送、多路复用。
答:对。
随机IO:假设咱们所须要的数据是随机分散在磁盘的不一样页的不一样扇区中的,那么找到相应的数据须要等到磁臂(寻址做用)旋转到指定的页,而后盘片寻找到对应的扇区,才能找到咱们所须要的一块数据,依次进行此过程直到找完全部数据,这个就是随机IO,读取数据速度较慢。
顺序IO:假设咱们已经找到了第一块数据,而且其余所需的数据就在这一块数据后边,那么就不须要从新寻址,能够依次拿到咱们所需的数据,这个就叫顺序IO。
答:对。
高级调度:即做业调度,按照必定策略将选择磁盘上的程序装入内存,并创建进程。(存在与多道批处理系统中)
中级调度:即交换调度,按照必定策略在内外存之间进行数据交换。
低级调度:即CPU调度(进程调度),按照必定策略选择就绪进程,占用cpu执行。
其中低度调度是必须的。
weak_ptr也是一个引用计数型智能指针,可是它不增长对象的引用计数,即弱引用。与之相对,shared_ptr是强引用,只要有一个指向对象的shared_ptr存在,该对象就不会析构,直到指向对象的最后一个shared_ptr析构或reset()时才会被销毁。
利用weak_ptr,咱们能够解决常见的空悬指针问题以及循环引用问题。
SPX(Sequenced Packet Exchange protocol,顺序包交换)协议是Novell开发的用在NetWare中的协议,用来确保信息成功传送。SPX使用NetWare的IPX协议做为它的传递机制并在网络结点间提供客户服务器和层对层的交互通讯。它工做在传输层。
* 2.若是客户端直接CLOSED,而后又再次向服务器发起一个新链接,谁也不能保证新发起的链接和刚关闭的链接的端口号是不一样的,有可能新、老链接的端口号就是同样的。假设新、老链接端口号一致,若老链接的一些数据仍滞留在网络中,这些滞留数据在新链接创建后才到达服务器,鉴于先后端口号一致,TCP协议就默认这些数据属于新链接,因而数据就这样乱成一锅粥了。因此TCP链接还要在TIME_WAIT状态下等待2MSL,确保全部老链接的数据都在网络中消失!
3.首先说明什么是MSL,MSL是Maximum Segment Lifetime的缩写,译为报文最大生存时间,也就是任何报文在网络上存活的最大时间,一旦超过该时间,报文就会被丢弃。2MSL也就是指的2倍MSL的时间。
为何是2倍呢?
当B接收到此消息,即认为双方达成了同步:双方都知道链接能够释放了,此时B能够安全地释放此TCP链接所占用的内存资源、端口号。因此被动关闭的B无需任何wait time,直接释放资源。但,A并不知道B是否接到本身的ACK,A是这么想的:
1)若是B没有收到本身的ACK,会超时重传FiN那么A再次接到重传的FIN,会再次发送ACK
2)若是B收到本身的ACK,也不会再发任何消息,包括ACK
不管是1仍是2,A都须要等待,要取这两种状况等待时间的最大值,以应对最坏的状况发生,这个最坏状况是:
去向ACK消息最大存活时间(MSL) + 来向FIN消息的最大存活时间(MSL)。这偏偏就是2MSL( Maximum Segment Life)。等待2MSL时间,A就能够放心地释放TCP占用的资源、端口号,此时可使用该端口号链接任何服务器。同时也能保证网络中老的连接所有消失。
package com.cn.niochat; import java.io.IOException; import java.net.InetSocketAddress; import java.nio.channels.SocketChannel; import java.nio.charset.Charset; import java.util.Scanner; /** * 用Java实现nio的客户端 */ public class NioClient { public void start() throws IOException { /** * 连接服务器端 */ SocketChannel socketChannel = SocketChannel.open(new InetSocketAddress("127.0.0.1",8000)); //向服务器端发送数据 //从命令行获取数据,获取键盘的输入 Scanner scanner = new Scanner(System.in); while (scanner.hasNextLine()){ //获取这一行数据 String request = scanner.nextLine(); //若是有数据,则发送,且数据不为空 if(request != null && request.length() > 0){ socketChannel.write(Charset.forName("UTF-8").encode(request)); } } } public static void main(String[] args) throws IOException { NioClient nioClient = new NioClient(); nioClient.start(); } }
(25+16+17)×2+12×3+(5+10)×4=212。
游标。
Java的+表达式计算是从左往右的。如果两个整形,会求值,若其中之一是String,会拼接,且结果为String。1+1+“1”,先计算1+1,由于两个都是整形,求值=2,而后2+“1”,拼接,因此是
21,而“1”+1+1,先计算“1”+1,由于有String,结果为’11",再“11”+1就是“111”。
意思是:当父类变量引用子类对象时(Fu f = new Zi();
),在这个引用变量f指向的对象中,他的成员变量和静态方法与父类是一致的,他的非静态方法,在编译时是与父类一致的,运行时却与子类一致(发生了复写)。
class Fu { intnum = 5; static void method4() { System.out.println("fu method_4"); } void method3() { System.out.println("fu method_3"); } } class Zi extends Fu { intnum = 8; static void method4() {//注意点:静态方法不能重写 System.out.println("zi method_4"); } void method3() { System.out.println("zi method_3"); } } class DuoTaiDemo4 { public static void main(String[] args) { Fu f = new Zi(); System.out.println(f.num);//与父类一致 f.method4();//与父类一致 f.method3();//编译时与父类一致,运行时与子类一致 Zi z = new Zi(); System.out.println(z.num); z.method4(); z.method3(); } }