java后端面经1

hashmap的底层实现

使用的是数组+链表+红黑树
详情戳这里

LinkedList和ArrayList的区别

LinkedList:基于链表实现,增删O(1)查询O(n)

ArrayList:基于数组实现,增删O(n),查询O(1)

线程与进程的区别

一个进程就是一个应用程序,一个进程中可以有多个线程

事务ACID

原子性:一个事务是一个不可分割的单位,其中的操作要么都做,要么都不做

一致性:事务执行结束后,数据库的完整性约束没有被破坏,事务执行前后都是合法的数据

隔离性:事务内部的操作与其他事务是隔离的,并发执行的各个事务之间不能互相干扰

持久性:事务一旦提交,他对数据库的改变就应该是永久性的,接下来的其他操作或故障不应该对其有任何影响

如何预防死锁

给加锁设置时间,尝试获取锁的时候一旦超过时间就自动放弃对该锁的请求,并释放自己占用的锁

事务的隔离级别

1.读未提交:事务A可以读取到事务B修改过但未提交的数据。—脏读,不可重复读,幻读

2.读已提交:事务B只能在事务A修改过并且已提交后才能读取到事务B修改的数据,—解决脏读,但是仍然有幻读和不可重复读

3.可重复度:事务B只能在事务A修改过数据并提交后,自己也提交事务后,才能读取到事务A修改的数据。—解决脏读,不可重复读,但是仍然有幻读

4.可串行化:一旦事务中有写操作,那么只能等前面的事务全部执行完成后才能执行—解决了全部的问题

Java基础数据类型

byte char short int long double boolean float

面向对象特征

封装,继承,多态

接口与抽象类区别

  • Java抽象类可以提供某些方法的部分实现,而Java接口不可以(java 1.8中可以定义default方法体)
  • 接口强调特定功能的实现,而抽象类强调所属关系。
  • 接口成员变量默认为public static final,必须赋初值,不能被修改,其所有的成员方法都是publicabstract的,抽象类中成员变量默认default,可在子类中被重新定义,也可被重新赋值;抽象方法被abstract修饰,不能被privatestaticsynchronizednative等修饰,必须以分号结尾,不带花括号。
  • 接口被用于常用的功能,便于日后维护和添加删除,而抽象类更倾向于充当公共类的角色,不适用于日后重新对立面的代码修改。功能需要累积时用抽象类,不需要累积时用接口。

重写与重载区别

重写发生在父子类之间,子类重写父类的方法,子类重写的方法权限不能低于父类的权限,重载发生在同一个类中,方法名相同,返回值相同,但是参数不同

线程安全不线程不安全

两个线程同时修改同一个变量就会产生安全问题,可能会导致同一线程两次读取的值不相同

地址栏输入url回车后发生了什么

1.浏览器查找域名的IP地址

2.浏览器与目标服务器建立TCP连接

3.浏览器给web服务器发送一个HTTP请求

4.服务器处理请求

5.服务器发出一个HTML响应

6.释放TCP连接

7.浏览器显示页面

TCP协议和UDP协议的区别是什么

  • TCP协议是有连接的,有连接的意思是开始传输实际数据之前TCP的客户端和服务器端必须通过三次握手建立连接,会话结束之后也要四次挥手结束连接。而UDP是无连接的
  • TCP协议保证数据按序发送,按序到达,提供超时重传来保证可靠性,但是UDP不保证按序到达,甚至不保证到达,只是努力交付,即便是按序发送的序列,也不保证按序送到。
  • TCP协议所需资源多,TCP首部需20个字节(不算可选项),UDP首部字段只需8个字节。
  • TCP有流量控制和拥塞控制,UDP没有,网络拥堵不会影响发送端的发送速率
  • TCP是一对一的连接,而UDP则可以支持一对一,多对多,一对多的通信。
  • TCP面向的是字节流的服务,UDP面向的是报文的服务。

三次握手建立连接时,发送方再次发送确认的必要性?

主要是为了防止已失效的连接请求报文段突然又传到了B,因而产生错误。假定出现一种异常情况,即A发出的第一个连接请求报文段并没有丢失,而是在某些网络结 点长时间滞留了,一直延迟到连接释放以后的某个时间才到达B,本来这是一个早已失效的报文段。但B收到此失效的连接请求报文段后,就误认为是A又发出一次 新的连接请求,于是就向A发出确认报文段,同意建立连接。假定不采用三次握手,那么只要B发出确认,新的连接就建立了,这样一直等待A发来数据,B的许多 资源就这样白白浪费了。

四次挥手释放连接时,等待2MSL的意义?

  • 为了保证A发送的最后一个ACK报文段能够到达B。这个ACK报文段有可能丢失,因而使处在LAST-ACK状态的B收不到对已发送的FIN和ACK 报文段的确认。B会超时重传这个FIN和ACK报文段,而A就能在2MSL时间内收到这个重传的ACK+FIN报文段。接着A重传一次确认。
  • 防止上面提到的已失效的连接请求报文段出现在本连接中,A在发送完最有一个ACK报文段后,再经过2MSL,就可以使本连接持续的时间内所产生的所有报文段都从网络中消失。

常见的应用中有哪些是应用TCP协议的,哪些又是应用UDP协议的,为什么它们被如此设计?

  • 多播的信息一定要用udp实现,因为tcp只支持一对一通信。
  • 如果一个应用场景中大多是简短的信息,适合用udp实现,因为udp是基于报文段的,它直接对上层应用的数据封装成报文段,然后丢在网络中,如果信息量太大,会在链路层中被分片,影响传输效率。
  • 如果一个应用场景重性能甚于重完整性和安全性,那么适合于udp,比如多媒体应用,缺一两帧不影响用户体验,但是需要流媒体到达的速度快,因此比较适合用udp
  • 如果要求快速响应,那么udp听起来比较合适
  • 如果又要利用udp的快速响应优点,又想可靠传输,那么只能考上层应用自己制定规则了。
  • 常见的使用udp的例子:ICQ,QQ的聊天模块。

静态内部类会被编译成几个class?

1个class,名称为外部类名$内部类名.class

为什么内部类可以访问外部类的private的方法?

使用private关键字修饰了某个成员,只有这个成员所在的类和这个类的方法可以使用,其他的类都无法访问到这个private成员。

CAS是什么?

CAS:compareAndSet比较工作内存的值和主内存的值,如果这个值是期望的,那么就执行操作,如果不是就一直循环(底层是自旋锁)

CAS底层是靠Unsafe类实现的,unsafe类是java的后门,可以使用这个类操作内存

底层其实就是利用内存偏移量来计算下标,然后判断当前值是否满足期望,满足就修改

缺点:

  • 循环会耗时
  • 一次性只能保证一个共享变量的原子性
  • 存在ABA问题

ABA问题是什么?

ABA问题

  • 在多线程场景下CAS会出现ABA问题,关于ABA问题这里简单科普下,例如有2个线程同时对同一个值(初始值为A)进行CAS操作,这三个线程如下
    • 1.线程1,期望值为A,欲更新的值为B
    • 2.线程2,期望值为A,欲更新的值为B
  • 线程1抢先获得CPU时间片,而线程2因为其他原因阻塞了,线程1取值与期望的A值比较,发现相等然后将值更新为B,然后这个时候出现了线程3,期望值为B,欲更新的值为A,线程3取值与期望的值B比较,发现相等则将值更新为A,此时线程2从阻塞中恢复,并且获得了CPU时间片,这时候线程2取值与期望的值A比较,发现相等则将值更新为B,虽然线程2也完成了操作,但是线程2并不知道值已经经过了A->B->A的变化过程。

ABA问题带来的危害:

  • 小明在提款机,提取了50元,因为提款机问题,有两个线程,同时把余额从100变为50
    线程1(提款机):获取当前值100,期望更新为50,
    线程2(提款机):获取当前值100,期望更新为50,
    线程1成功执行,线程2某种原因block了,这时,某人给小明汇款50
    线程3(默认):获取当前值50,期望更新为100,
    这时候线程3成功执行,余额变为100,
    线程2从Block中恢复,获取到的也是100,compare之后,继续更新余额为50!!!
    此时可以看到,实际余额应该为100(100-50+50),但是实际上变为了50(100-50+50-50)这就是ABA问题带来的成功提交。
  • 解决方法: 在变量前面加上版本号,每次变量更新的时候变量的版本号都+1,即A->B->A就变成了1A->2B->3A。

什么是AQS?

AQS:AbstractQuenedSynchronizer抽象的队列式同步器。是除了java自带的synchronized关键字之外的锁机制。

AQS的全称为(AbstractQueuedSynchronizer),这个类在java.util.concurrent.locks包

AQS的核心思想是,如果被请求的共享资源空闲,则将当前请求资源的线程设置为有效的工作线程,并将共享资源设置为锁定状态,如果被请求的共享资源被占用,那么就需要一套线程阻塞等待以及被唤醒时锁分配的机制,这个机制AQS是用CLH队列锁实现的,即将暂时获取不到锁的线程加入到队列中。

CLH(Craig,Landin,and Hagersten)队列是一个虚拟的双向队列,虚拟的双向队列即不存在队列实例,仅存在节点之间的关联关系。AQS是将每一条请求共享资源的线程封装成一个CLH锁队列的一个结点(Node),来实现锁的分配。

用大白话来说,AQS就是基于CLH队列,用volatile修饰共享变量state,线程通过CAS去改变状态符,成功则获取锁成功,失败则进入等待队列,等待被唤醒。

AQS是自旋锁:在等待唤醒的时候,经常会使用自旋(while(!cas()))的方式,不停地尝试获取锁,直到被其他线程获取成功

泛型 List<Integer>List<String> 这两个的getClass是否相同?

相同,java有泛型擦除机制,List<String>List<Integer> 在编译后都变成 List

说说MySQL Innodb 索引底层实现?

底层使用B-树,B+树对索引进行管理

mysql的join关键字?

分为内连接inner join和外连接,外连接分为左连接left join,右连接right join

两表连接查询的时候,如果不加约束就会产生笛卡尔积效应

mysql的GroupBy关键字?

GROUP BY 语句根据一个或多个列对结果集进行分组。一般会将分组函数和GROUP BY 联合使用

volatile关键字的作用?

  • 保证可见性 在一处修改主内存的值,另一个线程可以立即知道
  • 不保证原子性 原子性就是不可分割的意思 线程A在执行任务的时候,不能被打扰的,也不能被分割,要么同时成功,要么同时失败
  • 禁止指令重排 指令重排:自己写的程序,计算机并不是按照自己写的那样去执行的

说说指令重排?

解释型语言是在运行期间执行编译+运行动作,所以运行效率较编译型语言低。

Java中有两个编译期:1、调用javac命令将Java代码编译成Java字节码;2、Unix派系平台上调用gcc命令将openjdk源码编译成汇编代码。

编译期间,Java中所谓的指令重排主要是说编译openjdk时的指令重排,将Java代码编译成Java字节码是没有做指令重排的。即你加不加volatile,生成的字节码文件是一样的。

指令重排是编译器优化中的一种,编译openjdk是启用了O2级编译器优化

O2级优化做了哪些优化?比如优化无效代码、编译期完成简单运算、处理编译期屏障……

因为现在的CPU都是采用乱序执行,这样在运行程序的过程中就带来了指令重排的现象。

HashMap多线程下resize()死循环?

多线程下,如果一个线程进行了resize()并进行了rehash(),加入线程1进行到第一步就被挂起,线程2开始resize(),线程2resize()完成之后,线程1又开始继续进行resize()此时就有链表成环的可能

参考文章http://t.csdn.cn/DlghJ

hashtable和hashmap区别

  • hashmap线程不安全,hashtable线程安全
  • HashMap继承自AbstractMap类,Hashtable继承自Dictionary类 但是都实现了Map接口
  • HashMap是没有contains方法的,而包括containsValue和containsKey方法,hashtable则保留了contains方法,效果同containsValue,还包括containsValue和containsKey方法。
  • Hashmap是允许key和value为null值的,用containsValue和containsKey方法判断是否包含对应键值对;HashTable键值对都不能为空,否则包空指针异常。
  • 两个计算hash值的方法不同,hashMap计算方法,hashtable直接使用hashCode来计算
  • HashMap在求hash值对应的位置索引时,index = (n - 1) & hash。将哈希表的大小固定为了2的幂,因为是取模得到索引值,HashTable在求hash值位置索引时计算index的方法int index = (hash & 0x7FFFFFFF) % tab.length;
  • HashMap 哈希扩容必须要求为原容量的2倍,而且一定是2的幂次倍扩容结果,而且每次扩容时,原来数组中的元素依次重新计算存放位置,并重新插入;而Hashtable扩容为原容量2倍加1;
  • hashmap在出现hash冲突且冲突数量大于8的时候就会进化为红黑树,hashtable只有链表
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值