java基础知识点

本文链接:https://blog.csdn.net/u012517198/article/details/103125392
Java基础

1、List 和 Set 的区别
list和set都是继承 collection 接口;
list特点:元素有放入顺序,元素可重复;
set特点:元素无放入顺序,元素不可重复,重复元素会覆盖掉;

2、HashSet 是如何保证不重复的
put调用了对象的hashCode和equals方法进行的判断,if (e.hash == hash && ((k = e.key) == key || key.equals(k)))
所以又得出一个结论:若要将对象存放到HashSet中并保证对象不重复,应根据实际情况将对象的hashCode方法和equals方法进行重写

3、HashMap 是线程安全的吗,为什么不是线程安全的(最好画图说明多线程环境下不安全)?
HashMap的size大于等于(容量*加载因子)的时候,会触发扩容的操作。
不安全,扩容时一个线程还没有执行完毕,当前线程cpu资源暂停,另一个线程接着之前操作,jdk1.7 HashMap在并发环境下多线程put后可能导致get死循环,具体表现为CPU使用率100%。jdk1.8 非volatile类型,导致数据覆盖。

4、HashMap 的扩容过程

5、final finally finalize
final关键字,可以修饰类、方法、变量。修饰类,这个类不能被继承;修饰方法,这个方法不能被重写;修饰变量,需要在声明变量时,赋初始值,之后不能修改。
finally是在异常处理时提供finally块来执行任何清除操作。不管有没有异常被抛出、捕获,finally块都会被执行。
finalize是方法名。finalize()方法是在垃圾收集器删除对象之前对这个对象调用的。

6、强引用 、软引用、 弱引用、虚引用
7、Java反射
8、Arrays.sort 实现原理和 Collection 实现原理
9、LinkedHashMap的应用
10、cloneable接口实现原理
11、异常分类以及处理机制

12、wait和sleep的区别
wait()方法属于Object类;sleep()方法属于Thread类;
调用wait()方法的过程中,线程会释放对象锁;调用sleep()方法的过程中,线程不会释放对象锁。

13、数组在内存中如何分配
//定义第一个数组
int[] arr=new int[3];
arr[0]=10;
arr[1]=20;
arr[2]=70;
第一步:栈存储局部变量(在方法定义中或方法声明上的变量),所以int[] arr 存放在了栈中;
第二步:new出的变量放在堆中,所以new int[3] 在堆中。
第三步:每一个new出来的东西都有地址值(系统随机分配),所以new int[3] 的地址值为0x001;把0x001赋给arr,在栈中的数组通过地址值找到堆中相应的地址。用数组名和编号的配合就可以找到数组中指定编号的元素,这种方法就叫做索引。
第四步:int类型的数据默认值为0
第五步:给数组中的每个元素赋值,把原先的默认值0干掉。
延伸:
当加上static修饰,变成 static int[] arr=new int[3]; arr会被放在方法区(持久代/非堆)中。

Java 并发

1、synchronized 的实现原理以及锁优化?
实现原理:
那么它具体是怎么实现在同步方法或者同步代码块中保证最多只会有一个线程来访问呢?
每个对象都是一个监视器锁(Monitor),其实JVM是通过进入和退出Monitor对象来实现方法和代码块的同步。具体来说就是JVM对synchronized修饰的方法或者代码块在编译后会插入monitorenter和 monitorexit两条指令,即在进入同步方法或者同步代码块之前插入monitorenter,在退出时插入monitorexit,这 样就能保证每次只有一个线程能够访问同步方法或者同步代码块。
锁优化:
为了减少获取锁和释放锁带来的性能消耗,在JDK1.6后引入了偏向锁和轻量级锁,在JDK1.6以后,锁一共有四种状态,级别从低到高:无锁状态、偏向锁状态、轻量级锁状态、重量级锁状态。
锁可以从低到高升级,但是不能降级,就是偏向锁可以升级到轻量级锁,但是轻量级锁不能降级到偏向锁。

synchronize是如何实现同步操作的呢?它通过以下三种方式实现同步:
对于普通同步方法,锁是当前实例对象。
对于静态同步方法,锁是当前类的class对象。
对于同步代码块,锁是synchronized{}中所配置的对象

2、volatile 的实现原理?
特点:
1.变量可见性:其一是保证该变量对所有线程可见,这里的可见性指的是当一个线程修改了变量的值,那么新的值对于其他线程是可以立即获取的。
2.禁止重排序:volatile 禁止了指令重排。
3.不保证原子性。
比 sychronized 更轻量级的同步锁
在访问 volatile 变量时不会执行加锁操作,因此也就不会使执行线程阻塞,因此 volatile 变量是一种比 sychronized 关键字更轻量级的同步机制。volatile 适合这种场景:一个变量被多个线程共享,线程直接给这个变量赋值。
原理:
当对非 volatile 变量进行读写的时候,每个线程先从内存拷贝变量到 CPU 缓存中。如果计算机有多个 CPU,每个线程可能在不同的 CPU 上被处理,这意味着每个线程可以拷贝到不同的 CPUcache 中。
而声明变量是 volatile 的,JVM 保证了每次读变量都从内存中读,跳过 CPU cache 这一步。

3、Java 的信号灯?
Semaphore是一种基于计数的信号量。它可以设定一个阀值,基于此,多个线程竞争获取许可信号做自己的申请后归还,超过阀值后,线程申请许可将会被阻塞。Semaphore可以用来构建一些对象池,资源池之类的,比如数据库连接池,我们也可以创建计数为1的Semaphore,将其作为一种类似互斥锁的机制,这也叫二元信号量,表示两种互斥状态。重要。
它的用法如下:
semaphore.availablePermits(); // 表示获取到资源后,减去1,如果小于0,表示资源都被占用
semaphore.acquire(); // 表示获取到资源权限
semaphore.release(); // 释放资源

4、synchronized 在静态方法和普通方法的区别?
synchronized修饰普通方法时锁对象是this对象,而使用两个对象去访问,不是同一把锁。
当synchronized修饰静态方法时,锁对象是class字节码文件对象,而两个对象是同一个class文件,所以使用的是一个锁。

5、怎么实现所有线程在等待某个事件的发生才会去执行?

6、CAS?CAS 有什么缺陷,如何解决?
CAS是英文单词Compare And Swap的缩写,翻译过来就是比较并替换。
CAS的思想很简单:三个参数,一个当前内存值V、旧的预期值A、即将更新的值B,当且仅当预期值A和内存值V相同时,将内存值修改为B并返回true,否则什么都不做,并返回false。
CAS的缺点:
1.CPU开销较大
在并发量比较高的情况下,如果许多线程反复尝试更新某一个变量,却又一直更新不成功,循环往复,会给CPU带来很大的压力。
2.不能保证代码块的原子性
CAS机制所保证的只是一个变量的原子性操作,而不能保证整个代码块的原子性。比如需要保证3个变量共同进行原子性的更新,就不得不使用Synchronized了。
3.ABA问题
这是CAS机制最大的问题所在。

 什么是ABA问题?
 比如说一个线程 one 从内存位置 V 中取出 A,这时候另一个线程 two 也从内存中取出 A,并且two 进行了一些操作变成了 B,然后 two 又将 V 位置的数据变成 A,这时候线程 one 进行 CAS 操作发现内    存中仍然是 A,然后 one 操作成功。尽管线程 one 的 CAS 操作成功,但是不代表这个过程就是没有问题的。
 怎么避免ABA问题?
 java并发包中提供了一个带有标记的原子引用类AtomicStampedReference和AtomicMarkableReference它可以通过控制变量值的版本来保证CAS的正确性。

7、synchronized 和 lock 有什么区别?
synchronized是java关键字;Lock是一个类;
synchronized不需要用户去手动释放锁,当synchronized方法或者synchronized代码块执行完之后,系统会自动让线程释放对锁的占用;而Lock则必须要用户去手动释放锁,如果没有主动释放锁,就有可能导致出现死锁现象;
多个线程进行读操作,用synchronized锁,当一个线程在进行读操作时,其他线程只能等待无法进行读操作;用lock锁,线程之间不会发生冲突,可以进行读操作;
通过Lock可以知道线程有没有成功获取到锁,synchronized没办法知道;
synchronize对线程的同步仅提供独占模式,而Lock即可以提供独占模式,也可以提供共享模式;
Lock可实现公平锁,需要参数设置,默认是非公平锁;synchronize只能是非公平锁。

8、Hashtable 是怎么加锁的 ?
在Hashtable的源码里,put,get,contains等方法都加了 synchronized 关键字的。
public synchronized V get(Object key){}
public synchronized V put(K key, V value) {}
public synchronized V remove(Object key){}

9、HashMap 的并发问题?
HashMap在高并发下可能引起死循环,造成cpu占用过高。

10、ConcurrenHashMap 介绍?1.8 中为什么要用红黑树?
ConcurrenHashMap锁方式是稍微细粒度的,内部采用分离锁(分段锁)的设计。它默认将Hash表分为16个分段,get,put,remove等常用操作只锁当前需要用到的分段;
JDK1.8相比1.7,当链表长度大于8时,会将链表结构转成红黑树,便于大数据量的查询,使时间复杂度由O(n)变成O(logN)

11、AQS

12、如何检测死锁?怎么预防死锁?

13、Java 内存模型?

14、如何保证多线程下 i++ 结果正确?
使用锁机制,或者原子类

15、线程池的种类,区别和使用场景?
1. newSingleThreadExecutor 创建一个单线程的线程池,它只会用唯一的工作线程来执行任务,保证所有任务按照指定顺序执行。
2. newFixedThreadPool 创建一个定长线程池,可控制线程最大并发数,超出的线程会在队列中等待。
3. newCachedThreadPool 创建一个可缓存的线程池。如果线程池的大小超过了处理任务所需要的线程,那么就会回收部分空闲(60秒不执行任务)的线程,当任务数增加时,此线程池又可以智能的添加新线程来处理任务。此线程池不会对线程池大小做限制,线程池大小完全依赖于操作系统(或者说JVM)能够创建的最大线程大小。
4.newScheduledThreadPool 创建一个定长线程池,此线程池支持定时以及周期性执行任务的需求。

16、分析线程池的实现原理和线程的调度过程?
17、线程池如何调优,最大数目如何确认?

18、ThreadLocal原理,用的时候需要注意什么?
ThreadLocal 的实现是基于的ThreadLocalMap,在ThreadLocalMap 中 ,它的key是一个弱引用 。

    ThreadLocal注意事项
    脏数据
    线程复用会产生脏数据。由于结程池会重用Thread对象,那么与Thread绑定的类的静态属性ThreadLocal变量也会被重用。如果在实现的线程run()方法体中不显式地调用remove() 清理与线程相关的ThreadLocal信息,那么倘若下一个结程不调用set() 设置初始值,就可能get() 到重用的线程信息,包括 ThreadLocal所关联的线程对象的value值。
    
    内存泄漏
    通常我们会使用使用static关键字来修饰ThreadLocal(这也是在源码注释中所推荐的)。在此场景下,其生命周期就不会随着线程结束而结束,寄希望于ThreadLocal对象失去引用后,触发弱引用机制来回收Entry的Value就不现实了。如果不进行remove() 操作,那么这个线程执行完成后,通过ThreadLocal对象持有的对象是不会被释放的。
    
    以上两个问题的解决办法很简单,就是在每次用完ThreadLocal时, 必须要及时调用remove()方法清理。
    
    父子线程共享线程变量
    很多场景下通过ThreadLocal来透传全局上下文,会发现子线程的value和主线程不一致。比如用ThreadLocal来存储监控系统的某个标记位,暂且命名为traceId。某次请求下所有的traceld都是一致的,以获得可以统一解析的日志文件。但在实际开发过程中,发现子线程里的traceld为null,跟主线程的并不一致。这就需要使用InheritableThreadLocal来解决父子线程之间共享线程变量的问题,使整个连接过程中的traceId一致。

引用类型
1. 强引用(Strong Reference):最为常见。如Object object = new Object();这样的变量声明和定义就会产生对该对象的强引用。只要对象有强引用指向,并且GC Roots可达,那么Java内存回收时,即使濒临内存耗尽,也不会回收该对象。
2. 软引用(Soft Reference):引用力度弱于强引用,用于非必须对象上。在即将OOM之前,垃圾回收器会把这些软引用指向的对象加入回收范围,以获得更多的内存空间。软引用主要用来缓存中间计算结果及不需要实时保存的用户行为等。
3. 弱引用(Weak Reference):引用强度较前两者更弱,也是用来描述非必需对象的。如果弱引用指向的对象只存在弱引用这条线路,则在下一次YGC时会被回收。由于YGC时间的不确定性,弱引用何时被回收也具有不确定性。调用 WeakReference. get()可能返回null,要注意空指针异常。
4. 虚引用(Phantom Reference):是极弱的一种引用关系,定义完成后就无法通过该引用获取指向的对象。为一个对象设置虚引用的唯一目的就是希望能在这个对象被回收时收到一个系统通知。虚引用必须与引用队列联合使用,当垃圾回收时,如果发现存在虚引用,就会在回收对象内存前,把这个虚引用加入与之关联的引用队列中。

19、CountDownLatch 和 CyclicBarrier 的用法,以及相互之间的差别?
20、LockSupport工具
21、Condition接口及其实现原理
22、Fork/Join框架的理解
23、分段锁的原理,锁力度减小的思考
24、八种阻塞队列以及各个阻塞队列的特性

25、ThreadLocal和Synchonized区别?
ThreadLocal和Synchonized都用于解决多线程并发訪问。
可是ThreadLocal与synchronized有本质的差别:
synchronized是利用锁的机制,使变量或代码块在某一时该仅仅能被一个线程訪问。它用于在多个线程间通信时可以获得数据共享。
ThreadLocal为每个线程都提供了变量的副本,使得每个线程在某一时间訪问到的并非同一个对象,这样就隔离了多个线程对数据的数据共享。

    java中的线程池 核心使用构造函数 采用ThreadPoolExecutor
    public ThreadPoolExecutor(int corePoolSize,int maximumPoolSize,long keepAliveTime,TimeUnit unit,BlockingQueue<Runnable> workQueue) {
        this(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue,Executors.defaultThreadFactory(), defaultHandler);
    }
    ThreadPoolExecutor 构造函数参数:
    1.核心池大小(相当于线程池初始化的一个大小) corePoolSize 
    2.线程池大小(最大线程池表示最大容量是多少) maximumPoolSize
    3.终止时间 keepAliveTime
    4.超时秒数 unit
    5.阻塞队列,泛型线程(假如创建5个线程,超出部分放在这里) workQueue
    
    线程池执行流程:
    用户提交的线程 -》核心线程池5 -》没有满-》 线程执行任务
    用户提交的线程 -》核心线程池5 -》满-》 线程缓存队列 -》 最大线程池 -》没有满 -》创建线程执行任务
    用户提交的线程 -》核心线程池5 -》满-》 线程缓存队列 -》 最大线程池 -》满 -》拒绝任务策略

Spring

1、BeanFactory 和 FactoryBean?
BeanFactory:以Factory结尾,表示它是一个工厂类,是用于管理Bean的一个工厂
FactoryBean:以Bean结尾,表示它是一个Bean,不同于普通Bean的是:它是实现了FactoryBean接口的Bean,根据该Bean的Id从BeanFactory中获取的实际上是FactoryBean的getObject()返回的对象,而不是FactoryBean本身,如果要获取FactoryBean对象,可以在id前面加一个&符号来获取。

2、Spring IOC 的理解,其初始化过程?
IOC(Inversion of Control)即控制反转,在我们以往的编程中如果需要一个bean往往需要去手动去new一个出来。而spring帮我们解决了这个问题,在spring中我们只需要去定义bean,spring就会自动的帮我们实例化并管理Bean。而这些Bean就管理在spring容器中。

容器的初始化是通过refresh()方法来完成的,总共包括三个步骤:
定位:通过Resource定位BeanDefinition,BeanDefinition抽象了对bean的定义,比如bean的信息,依赖关系等。这个过程可以想象成寻找bean的过程。
载入:BeanDefinition的信息已经定位到了,第二步就是把定义的BeanDefinition在Ioc容器中转化成一个Spring内部标示的数据结构的过程。
注册:将抽象好的BeanDefinition统一注册到IoC容器中,IoC容器是通过hashMap来维护BeanDefinition信息的,key为beanName,value为BeanDefinition。

3、BeanFactory 和 ApplicationContext?
BeanFactory:
是Spring里面最低层的接口,提供了最简单的容器的功能,只提供了实例化对象和拿对象的功能;
ApplicationContext:
应用上下文,继承BeanFactory接口,它是Spring的一各更高级的容器,提供了更多的有用的功能;

  1. 国际化(MessageSource)
  2. 访问资源,如URL和文件(ResourceLoader)
  3. 载入多个(有继承关系)上下文 ,使得每一个上下文都专注于一个特定的层次,比如应用的web层
  4. 消息发送、响应机制(ApplicationEventPublisher)
  5. AOP(拦截器)

两者创建对象区别:
BeanFactory 在解析配置文件时并不会初始化对象,只有在使用对象时(getBean())才会对该对象进行初始化
ApplicationContext 在解析配置文件时对配置文件中的所有对象都初始化了,getBean()方法只是获取对象的过程

4、Spring Bean 的生命周期,如何被管理的?
Spring 容器可以管理 singleton 作用域 Bean 的生命周期,在此作用域下,Spring 能够精确地知道该 Bean 何时被创建,何时初始化完成,以及何时被销毁。
而对于 prototype 作用域的 Bean,Spring 只负责创建,当容器创建了 Bean 的实例后,Bean 的实例就交给客户端代码管理,Spring 容器将不再跟踪其生命周期。每次客户端请求 prototype 作用域的 Bean时,Spring 容器都会创建一个新的实例,并且不会管那些被配置成 prototype 作用域的 Bean 的生命周期。

5、Spring Bean 的加载过程是怎样的?
①获取beanFactory -》②实现BeanPostProcessor接口 -》③通过反射实例化目标bean -》④注入目标bean属性 -》⑤若实现BeanNameAware接口,则通过setBeanNam设置id -》⑥若实现BeanFactoryAware接口,则通过setBeanFactory设置factory -》⑦调用beanPostProcessor的postProcessorBeforeInitialization() -》⑧初始化,若实现InitializingBean接口,则调用其afterPropertiesSet()方法,然后调用自定义的init-method -》⑨调用beanPostProcessor的postProcessorAfterInitialization() -》⑩通过disposableBean或自定义注入destroy()方法

6、如果要你实现Spring AOP,请问怎么实现?
7、如果要你实现Spring IOC,你会注意哪些问题?

8、Spring 是如何管理事务的,事务管理机制?
Spring的事务机制包括声明式事务和编程式事务。
如何管理的:
Spring事务管理主要包括3个接口,Spring的事务主要是由他们三个共同完成的。
1)PlatformTransactionManager:事务管理器–主要用于平台相关事务的管理
主要有三个方法:
commit 事务提交;
rollback 事务回滚;
getTransaction 获取事务状态。
2)TransactionDefinition:事务定义信息–用来定义事务相关的属性,给事务管理器PlatformTransactionManager使用
这个接口有下面四个主要方法:
getIsolationLevel:获取隔离级别;
getPropagationBehavior:获取传播行为;
getTimeout:获取超时时间;
isReadOnly:是否只读(保存、更新、删除—对数据进行操作-变成可读写的,查询-设置这个属性为true,只能读不能写),事务管理器能够根据这个返回值进行优化。
3)TransactionStatus:事务具体运行状态–事务管理过程中,每个时间点事务的状态信息。
例如它的几个方法:
hasSavepoint():返回这个事务内部是否包含一个保存点,
isCompleted():返回该事务是否已完成,也就是说,是否已经提交或回滚
isNewTransaction():判断当前事务是否是一个新事务

9、Spring 的不同事务传播行为有哪些,干什么用的?
在TransactionDefinition定义中包括了如下几个表示传播行为的常量:
支持当前事务的情况:
TransactionDefinition.PROPAGATION_REQUIRED: 如果当前存在事务,则加入该事务;如果当前没有事务,则创建一个新的事务。
TransactionDefinition.PROPAGATION_SUPPORTS: 如果当前存在事务,则加入该事务;如果当前没有事务,则以非事务的方式继续运行。
TransactionDefinition.PROPAGATION_MANDATORY: 如果当前存在事务,则加入该事务;如果当前没有事务,则抛出异常。
不支持当前事务的情况:
TransactionDefinition.PROPAGATION_REQUIRES_NEW: 创建一个新的事务,如果当前存在事务,则把当前事务挂起。
TransactionDefinition.PROPAGATION_NOT_SUPPORTED: 以非事务方式运行,如果当前存在事务,则把当前事务挂起。
TransactionDefinition.PROPAGATION_NEVER: 以非事务方式运行,如果当前存在事务,则抛出异常。
其他情况:
TransactionDefinition.PROPAGATION_NESTED: 如果当前存在事务,则创建一个事务作为当前事务的嵌套事务来运行;如果当前没有事务,则该取值等价于TransactionDefinition.PROPAGATION_REQUIRED。

10、Spring 中用到了那些设计模式?
11、Spring MVC 的工作原理?
12、Spring 循环注入的原理?
13、Spring AOP的理解,各个术语,他们是怎么相互工作的?
14、Spring 如何保证 Controller 并发的安全?

Netty

1、BIO、NIO和AIO
BIO:同步阻塞I/O 1.4之前只有BIO 适用于连接数目比较小且固定的架构,这种方式对服务器资源要求比较高,并发局限于应用中
NIO:同步非阻塞I/O 1.4开始有NIO 适用于连接数目多且连接比较短(轻操作)的架构,比如聊天服务器
AIO:异步非阻塞I/O 1.7开始有AIO 适用于连接数目多且连接比较长(重操作)的架构,比如相册服务器

2、Netty 的各大组件
Channel
ChannelFuture
EventLoop
ChannelHandler
ChannelPipeline

3、Netty的线程模型
4、TCP 粘包/拆包的原因及解决方法
5、了解哪几种序列化协议?包括使用场景和如何去选择
6、Netty的零拷贝实现
7、Netty的高性能表现在哪些方面

分布式相关

1、Dubbo的底层实现原理和机制
2、描述一个服务从发布到被消费的详细过程
3、分布式系统怎么做服务治理
4、接口的幂等性的概念
5、消息中间件如何解决消息丢失问题
6、Dubbo的服务请求失败怎么处理
dubbo启动时默认有重试机制和超时机制。
超时机制的规则是如果在一定的时间内,provider没有返回,则认为本次调用失败,
重试机制在出现调用失败时,会再次调用。如果在配置的调用次数内都失败,则认为此次请求异常,抛出异常

7、重连机制会不会造成错误
8、对分布式事务的理解
9、如何实现负载均衡,有哪些算法可以实现?
1、轮询法:将请求按顺序轮流地分配到后端服务器上,它均衡地对待后端的每一台服务器,而不关心服务器实际的连接数和当前的系统负载。
2、随机法:通过系统的随机算法,根据后端服务器的列表大小值来随机选取其中的一台服务器进行访问。由概率统计理论可以得知,随着客户端调用服务端的次数增多,其实际效果越来越接近于平均分配调用量到后端的每一台服务器,也就是轮询的结果。
3、源地址哈希法:源地址哈希的思想是根据获取客户端的IP地址,通过哈希函数计算得到的一个数值,用该数值对服务器列表的大小进行取模运算,得到的结果便是客服端要访问服务器的序号。采用源地址哈希法进行负载均衡,同一IP地址的客户端,当后端服务器列表不变时,它每次都会映射到同一台后端服务器进行访问。
4、加权轮询法:不同的后端服务器可能机器的配置和当前系统的负载并不相同,因此它们的抗压能力也不相同。给配置高、负载低的机器配置更高的权重,让其处理更多的请;而配置低、负载高的机器,给其分配较低的权重,降低其系统负载,加权轮询能很好地处理这一问题,并将请求顺序且按照权重分配到后端。
5、加权随机法:与加权轮询法一样,加权随机法也根据后端机器的配置,系统的负载分配不同的权重。不同的是,它是按照权重随机请求后端服务器,而非顺序。
6、最小连接数法:最小连接数算法比较灵活和智能,由于后端服务器的配置不尽相同,对于请求的处理有快有慢,它是根据后端服务器当前的连接情况,动态地选取其中当前积压连接数最少的一台服务器来处理当前的请求,尽可能地提高后端服务的利用效率,将负责合理地分流到每一台服务器。

10、Zookeeper的用途,选举的原理是什么?
11、数据的垂直拆分水平拆分。
12、zookeeper原理和适用场景
13、zookeeper watch机制
14、redis/zk节点宕机如何处理
15、分布式集群下如何做到唯一序列号
16、如何做一个分布式锁
17、用过哪些MQ,怎么用的,和其他mq比较有什么优缺点,MQ的连接是线程安全的吗
18、MQ系统的数据如何保证不丢失
19、列举出你能想到的数据库分库分表策略;分库分表后,如何解决全表查询的问题
20、zookeeper的选举策略
21、全局ID

数据库

1、mysql分页有什么优化
1、尽量给出查询的大致范围 SELECT c1,c2,cn… FROM table WHERE id>=20000 LIMIT 10;
2、子查询法 SELECT c1,c2,cn… FROM table WHERE id>= (SELECT id FROM table LIMIT 20000,1) LIMIT 10;
3、可以使用 between and 来查询:SELECT * FROM ORDERS_HISTORY WHERE TYPE=2 AND ID BETWEEN 1000000 AND 1000100 LIMIT 100;

2、悲观锁、乐观锁
悲观锁就是每次操作时都要通过获取锁才能进行对相同数据的操作
乐观锁不是数据库自带的,需要我们自己去实现。

3、组合索引,最左原则
4、mysql 的表锁、行锁
表锁:偏向MyISAM存储引擎,开销小,加锁快;无死锁;锁定粒度大,发生锁冲突的概率最高,并发度最低。
行锁:偏向InnoDB存储引擎,开销大,加锁慢;会出现死锁;锁定粒度最小,发生锁冲突的概率最低,并发度也最高。

5、mysql 性能优化
MySQL优化方案:
1.数据库设计要合理(3F)
2.添加索引(普通索引、主键索引、唯一索引、全文索引)底层:B-Tree和B+Tree 和二叉树算法一样,减少全表扫描
3.分表分库技术(取模分表、水平分割、垂直分割)
4.读写分离
5.存储过程
6.配置MySQL最大连接数 my.ini
7.mysql服务器升级
8.随时清理碎片化
9.sql语句调优 核心

6、mysql的索引分类:B+,hash;什么情况用什么索引

7、事务的特性和隔离级别
事务特性 ACID:
原子性(Atomicity):事务中的逻辑要全部执行,不可分割。(原子是物理中最小单位)
一致性(Consistency):事务执行的结果必须是使数据库从一个一致性状态变到另一个一致性状态
隔离性(Isolation):一个事务的执行过程中不能影响到其他事务的执行,即一个事务内部的操作及使用的数据对其他事务是隔离的,并发执行时各个事务之间互不干扰。
持久性(Durability):即一个事务一旦提交,它对数据库的改变是永久性的。之后的其他操作不应该对其执行结果有任何影响。

 隔离级别:
 Serializable (串行化):可避免脏读、不可重复读、幻读的发生。
 Repeatable read (可重复读):可避免脏读、不可重复读的发生。
 Read committed (读已提交):可避免脏读的发生。
 Read uncommitted (读未提交):最低级别,任何情况都无法保证。

缓存

1、Redis用过哪些数据类型,以及Redis底层怎么实现
Redis支持五种数据类型:string(字符串),hash(哈希),list(列表),set(集合)及zset(sorted set:有序集合)。
类型常量 对象的名称
redis_string 字符串对象
redis_list 列表对象
redis_hash 哈希对象
redis_set 集合对象
redis_zset 有序集合对象

 Redis对象底层数据结构
 底层数据结构共有八种:
 编码常量                                        编码所对应的底层数据结构
 redis_encoding_int                    long 类型的整数
 redis_encoding_embstr            embstr 编码的简单动态字符串
 redis_encoding_raw                    简单动态字符串
 redis_encoding_ht                    字典
 redis_encoding_linkedlist    双端链表
 redis_encoding_ziplist            压缩列表
 redis_encoding_intset            整数集合
 redis_encoding_skiplist        跳跃表和字典

 字符串对象:字符串对象的编码可以是int、raw或者embstr。
 列表对象:列表对象的编码可以是ziplist或者linkedlist。
 哈希对象:哈希对象的底层实现可以是ziplist或者hashtable。
 集合对象:集合对象的编码可以是intset或者hashtable。
 有序集合对象:有序集合的编码可能两种,一种是ziplist,另一种是skiplist与dict的结合。

2、Redis缓存穿透,缓存雪崩
缓存穿透:缓存穿透是指缓存和数据库中都没有的数据,而用户不断发起请求,如发起为id为“-1”的数据或id为特别大不存在的数据。这时的用户很可能是攻击者,攻击会导致数据库压力过大。
解决方案:

  1. 接口层增加校验,如用户鉴权校验,id做基础校验,id<=0的直接拦截;
  2. 从缓存取不到的数据,在数据库中也没有取到,这时也可以将key-value对写为key-null,缓存有效时间可以设置短点,如30秒(设置太长会导致正常情况也没法使用)。这样可以防止攻击用户反复用同一个id暴力攻击
 缓存击穿:缓存击穿是指缓存中没有但数据库中有的数据(一般是缓存时间到期),这时由于并发用户特别多,同时读缓存没读到数据,又同时去数据库去取数据,引起数据库压力瞬间增大,造成过大压力。
 解决方案:
  1. 设置热点数据永远不过期。
  2. 对缓存查询加锁,如果KEY不存在,就加锁,然后查DB入缓存,然后解锁;其他进程如果发现有锁就等待,然后等解锁后返回数据或者进入DB查询
 缓存雪崩:缓存雪崩是指缓存中数据大批量到过期时间,而查询数据量巨大,引起数据库压力过大甚至down机。和缓存击穿不同的是,缓存击穿指并发查同一条数据,缓存雪崩是不同数据都过期了,很多数据都查不到从而查数据库。
 解决方案:
  1. 缓存数据的过期时间设置随机,防止同一时间大量数据过期现象发生。
  2. 如果缓存数据库是分布式部署,将热点数据均匀分布在不同搞得缓存数据库中。

3、如何使用Redis来实现分布式锁
涉及到重复提交或交易的地方
场景一:提交订单

4、Redis的并发竞争问题如何解决
Redis的并发竞争问题,主要是发生在并发写竞争。
当我们有2个甚至多个线程去操作一个redis里的值时,
比如我拿到商品的剩余库存要去相减,
首先第一个线程拿到的库存是10 要减去1
第二个拿到的也是10 也要减一,
我们期望的情况下是最后库存是8
解决方案
方案1:利用redis自带的incr命令,decr命令(Redis Incr 命令将 key 中储存的数字值增一。如果 key 不存在,那么 key 的值会先被初始化为 0 ,然后再执行 INCR 操作)。
(Redis Decr 命令将 key 中储存的数字值减一。如果 key 不存在,那么 key 的值会先被初始化为 0 ,然后再执行 DECR 操作。)
方案2:可以使用独占锁的方式,类似操作系统的mutex机制。(有点困难)
方案3:使用乐观锁的方式进行解决(成本较低,非阻塞,性能较高)
watch price
get price $price
$price = $price + 10
multi
set price $price
exec
解释一下:
watch这里表示监控该key值,后面的事务是有条件的执行,如果从watch的exec语句执行时,watch的key对应的value值被修改了,则事务不会执行。
方案4:这个是针对客户端来的,在代码里要对redis操作的时候,针对同一key的资源,就先进行加锁(java里的synchronized或lock)。
方案5:利用redis的setnx实现内置的锁。

5、Redis持久化的几种方式,优缺点是什么,怎么实现的
Redis持久化分为AOF与RDB两种模式。默认持久化备份文件:dump.rdb。redis.conf默认读取的就是dump.rdb。
RDB:以数据方式存储
AOF:以日志形式存储,不保存get信息
AOF文件比RDB文件大,且恢复速度慢。AOF默认关闭。

6、Redis的缓存失效策略
7、Redis集群,高可用,原理

8、Redis缓存分片
Redis 集群的数据分片是redis进行分布式存储的一种,它引入了hash槽的概念,每个redis节点存储一定范围的hash槽 ,redis集群有16384个hash槽,每个key通过CRC16校验后对16384取模来决定存储在哪个槽哪个节点
比如当前有三个节点 那么:
节点 A 包含 0 到 5500号哈希槽.
节点 B 包含5501 到 11000 号哈希槽.
节点 C 包含11001 到 16384号哈希槽.

9、Redis的数据淘汰策略

JVM

1、详细jvm内存模型
运行时内存模型,分为线程私有和共享数据区两大类,其中线程私有的数据区包含程序计数器、虚拟机栈、本地方法区,所有线程共享的数据区包含Java堆、方法区,在方法区内有一个常量池。
(1)线程私有区:
程序计数器,记录正在执行的虚拟机字节码的地址;
虚拟机栈:方法执行的内存区,每个方法执行时会在虚拟机栈中创建栈帧;
本地方法栈:虚拟机的Native方法执行的内存区;
(2)线程共享区:
Java堆:对象分配内存的区域;
方法区:存放类信息、常量、静态变量、编译器编译后的代码等数据;
常量池:存放编译器生成的各种字面量和符号引用,是方法区的一部分。

2、讲讲什么情况下回出现内存溢出,内存泄漏?
内存溢出 out of memory,是指程序在申请内存时,没有足够的内存空间供其使用,出现out of memory;比如申请了一个integer,但给它存了long才能存下的数,那就是内存溢出。
内存泄露 memory leak,是指程序在申请内存后,无法释放已申请的内存空间。对象已经没有被应用程序使用,但是垃圾回收器没办法移除它们,因为还被引用着。
内存泄漏:定义很多静态变量,垃圾是不会回收的,这个对象又没有被引用,再申请内存时报错内存泄漏。

3、说说Java线程栈
JVM线程堆栈是一个给定时间的快照,它能向你提供所有被创建出来的Java线程的完整清单.每一个被发现的Java线程都会给你如下信息:
– 线程的名称;经常被中间件厂商用来识别线程的标识,一般还会带上被分配的线程池名称以及状态 (运行,阻塞等等.)
– 线程类型 & 优先级,例如 : daemon prio=3 * 中间件程序一般以后台守护的形式创建他们的线程,这意味着这些线程是在后台运行的;它们会向它们的用户提供服务,例如:向你的Java EE应用程序 *
– Java线程ID,例如 : tid=0x000000011e52a800 * 这是通过 java.lang.Thread.getId() 获得的Java线程ID,它常常用自增长的长整形 1…n* 实现
– 原生线程ID,例如 : nid=0x251c** ,之所以关键是因为原生线程ID可以让你获得诸如从操作系统的角度来看那个线程在你的JVM中使用了大部分的CPU时间等这样的相关信息. **
– Java线程状态和详细信息,例如: waiting for monitor entry [0xfffffffea5afb000] java.lang.Thread.State: BLOCKED (on object monitor)

  • 可以快速的了解到线程状态极其当前阻塞的可能原因 *
    – Java线程栈跟踪;这是目前为止你能从线程堆栈中找到的最重要的数据. 这也是你花费最多分析时间的地方,因为Java栈跟踪向提供了你将会在稍后的练习环节了解到的导致诸多类型的问题的根本原因,所需要的90%的信息。

4、JVM 年轻代到年老代的晋升过程的判断条件是什么呢?
根据内存中对象的存活周期不同,将内存划分为几块,Java的虚拟机中一般把内存划分为新生代和老年代,当新创建对象时一般在新生代中分配内存空间,
当新生代垃圾连续回收几次之后(默认15次)仍然存活的对象会被移动到老年代内存中,当大对象在新生代中无法找到足够的连续内存时也直接在老年代中创建。

5、JVM 出现 fullGC 很频繁,怎么去线上排查问题?
6、类加载为什么要使用双亲委派模式,有没有什么场景是打破了这个模式?
7、类的实例化顺序
父类静态变量->父类静态代码块->子类静态变量->子类静态代码块->父类非静态变量(父类实例成员变量)->父类构造函数->子类非静态变量(子类实例成员变量)->子类构造函数。

8、JVM垃圾回收机制,何时触发MinorGC等操作
Minor GC 也被称为新生代 GC,指发生在新生代(PSYoungGen)的垃圾收集动作,新生代包括三块内存区域 eden 区,from (From Survivor)区 与 to(To Survivor) 区。对象优先在 eden 创建并区分配内存,当 eden 区内存无法为一个新对象分配内存时,就会触发 Minor GC。

9、JVM 中一次完整的 GC 流程(从 ygc 到 fgc)是怎样的
对象优先在新生代区中分配,若没有足够空间,Minor GC;
大对象(需要大量连续内存空间)直接进入老年态;长期存活的对象进入老年态。如果对象在新生代出生并经过第一次MGC后仍然存活,年龄+1,若年龄超过一定限制(默认:15),则被晋升到老年态。

10、各种回收器,各自优缺点,重点CMS、G1
1. 串行垃圾回收器(Serial Garbage Collector) 单线程收集垃圾 效率低,单线程执行回收操作,回收期间暂停所有应用线程的执行,client模式下的默认回收器,通过-XX:+UseSerialGC命令行可选项强制指定。一般不用串行收集器。
单线程收集器:Serial收集器 新生代 复制算法;Serial Old收集器 老年代 标记-整理。
2. 并行垃圾回收器(Parallel Garbage Collector)在串行回收器基础上做了改进,他可以使用多个线程同时进行垃圾回收,对于计算能力强的计算机而言,可以有效的缩短垃圾回收所需的实际时间。并行回收器工作时的线程数量可以使用XX:ParallelGCThreads参数指定。
并行回收器:ParNew收集器 新生代 复制算法;Parallel Scavenge收集器 新生代 复制算法;Parallel Old收集器 老年代 标记-整理
3. 并发标记扫描垃圾回收器(CMS Garbage Collector):一款以获取最短回收停顿时间为目标的收集器,是基于“标记-清除”算法实现的,分为4个步骤:初始标记、并发标记、重新标记、并发清除。缺点是:对CPU资源非常敏感、无法处理浮动垃圾、基于“标记-清除”算法导致收集结束会产生大量空间碎片。
4. G1垃圾回收器(G1 GarbageCollector):面向服务端应用的垃圾收集器,过程:初始标记;并发标记;最终标记;筛选回收。整体上看是“标记-整理”,局部看是“复制”,不会产生内存碎片。

11、各种回收算法
1. 引用计数法
2. 复制算法
3. 标记清除
4. 标记压缩
5. 分代算法

引用计数法 :
    给对象中添加一个引用计数器,每当一个地方引用它时,计数器值就加1;当引用失效时,计数器值就减1;任何时刻计数器都为0时的对象就是不再被使用的,垃圾收集器将回收该对象使用的内存。 用在eden区。
    优点:引用计数收集器可以很快的执行,交织在程序运行中。
    缺点:无法检测出循环引用。如父对象有一个子对象的引用,子对象反过来引用父对象,这样他们的引用计数永远不可能为0,而且每次加减非常浪费内存。
    引用计数,每个对象都会有一个标记,默认是15次,gc回收时,为0时 gc直接回收掉。不为0时,对象没有被引用减1,被引用加1。如果次数加到大于15,进入到新生代s0区,或者s1区(复制算法),再增加次数比较多的时候进入老年代(分代算法)。

    复制算法:
    复制算法--新生代(s0、s1大小是相等的,只有一个区域能存活) 
    创建user1对象先存放eden区,当gc线程回收的时候发现user1对象经常被引用,将user放到s0区。
    创建user2对象也存放eden区,当gc线程回收的时候发现user1对象经常被引用,将user放到s0区。
    当gc检查到user1对象不再被引用的时候,会将user2对象复制到s1区,这个时候s0区全部清除。
    创建user3对象,同理先放eden区,当user3经常被引用,这个时候user3会被迁移到s1区(只有一个区能存活)
  当user2不被引用时,user3会被复制到s0区,这个时候,s1区全部被清除掉。

    标记清除与标记压缩
    标记清除和标记压缩一般用在老年代。 
    标记清除算法:0可达 1不可达。标记清除算法为每一个对象做一个标记,0可达,1不可达。对象没有经常使用标记为1不可达。
    创建user1,user2,user3对象(堆内存)。当垃圾回收器发现user1对象没有被经常使用,标记为1不可达,这时候将user1对象删除,但是user1空间还保留。当user2对象和user3对象都标记为不可达是,不是一起删除,是一个一个删除。

    标记压缩算法:0可达 1不可达。
创建user1,user2,user3对象(堆内存)。当垃圾回收器发现user1,user2对象没有被经常使用,标记为1不可达。
    标记压缩算法首先会排下序,将标记为不可达的对象放在前面,这时候会一起删除,同时释放内存空间。

    分代算法:
    根据内存中对象的存活周期不同,将内存划分为几块,Java的虚拟机中一般把内存划分为新生代和老年代,当新创建对象时一般在新生代中分配内存空间,当新生代垃圾连续回收几次之后仍然存活的对象会被移动到老年代内存中,当大对象在新生代中无法找到足够的连续内存时也直接在老年代中创建。
对于新生代和老年代来说,新生代回收频率很高,但是每次回收耗时很短,而老年代回收频率较低,但是耗时会相对较长,所以应该尽量减少老年代GC。

    新生代:eden区  采用引用计数算法; s0 s1区 采用复制算法。
    老年代:采用标记压缩算法,一般不会用标记清除算法,会产生碎片。

12、OutOfMemoryError错误,stackoverflow错误,permgen space错误
1. StackOverflowError(栈溢出)错误主要出现:
在虚拟机栈中(线程请求的栈深度大于虚拟机栈锁允许的最大深度)
2. permgen space错误(针对jdk之前1.7版本):
加载到内存中的class数量太多或体积太大。
常量池内存溢出

我们先看看 PermGen 是用来干什么的。
    在JDK1.7及之前的版本, 永久代(permanent generation) 主要用于存储加载/缓存到内存中的 class 定义, 包括 class 的 名称(name), 字段(fields), 方法(methods)和字节码(method bytecode); 以及常量池(constant pool information); 对象数组(object arrays)/类型数组(type arrays)所关联的 class, 还有 JIT 编译器优化后的class信息等。
    很容易看出, PermGen的使用量和JVM加载到内存中的class 数量/大小有关。可以说 java.lang.OutOfMemoryError: PermGen space 的主要原因, 是加载到内存中的 class 数量太多或体积太大。

1、hashmap hastable 底层实现什么区别?hashtable和concurrenthashtable呢?
2、hashmap和treemap什么区别?低层数据结构是什么?
3、线程池用过吗都有什么参数?底层如何实现的?
4、sychnized和Lock什么区别?sychnize 什么情况情况是对象锁? 什么时候是全局锁为什么?
5、ThreadLocal 是什么底层如何实现?写一个例子呗?
6、volitile的工作原理?
7、cas知道吗如何实现的?
Compare and Swap 比较并刷新到缓存。通过比较线程旧值跟内存中的值是否相等来判断当前的值能否刷新到缓存中。

8、请用至少四种写法写一个单例模式?
9、请介绍一下JVM内存模型?用过什么垃圾回收器都说说呗
10、线上发送频繁full gc如何处理? CPU 使用率过高怎么办?
11、知道字节码吗?字节码都有哪些?Integer x =5,int y =5,比较x =y 都经过哪些步骤?
12、讲讲类加载机制呗都有哪些类加载器,这些类加载器都加载哪些文件?
13、手写一下类加载Demo
14、知道osgi吗? 他是如何实现的?
15、请问你做过哪些JVM优化?使用什么方法达到什么效果?
16、classforName(“java.lang.String”)和String classgetClassLoader() LoadClass(“java.lang.String”) 什么区别啊?
17、探查Tomcat的运行机制即框架?
18、分析Tomcat线程模型?
19、Tomcat系统参数认识和调优?
20、MySQL底层B+Tree机制?
21、SQL语句如如如何优化?
22、spring都有哪些机制啊AOP底层如何实现的啊IOC呢??
23、cgLib知道吗?他和jdk动态代理什么区别?手写一个jdk动态代理呗?

24、使用mysq1索引都有哪些原则? ?索引什么数据结构? 3+tree 和B tree 什么区别?
25、MySQL有哪些存储引擎啊?都有啥区别? 要详细!
26、设计高并发系统数据库层面该怎么设计??数据库锁有哪些类型?如何实现呀?
27、数据库事务有哪些?
28、如何设计可以动态扩容缩容的分库分表方案?
29、用过哪些分库分表中间件,有啥优点和缺点?讲一下你了解的分库分表中间件的底层实现原理?
30、我现在有一个未分库分表的系统,以后系统需分库分表,如何设计,让未分库分表的系统动态切换到分库分表的系统上?TCC? 那若出现网络原因,网络连不通怎么办啊?
31、分布式事务知道吗? 你们怎么解决的?
32、为什么要分库分表啊?
33、RPC通信原理,分布式通信原理
34、分布式寻址方式都有哪些算法知道一致性hash吗?手写一下java实现代码??你若userId取摸分片,那我要查一段连续时间里的数据怎么办?
35、如何解决分库分表主键问题有什么实现方案??
36、redis和memcheched 什么区别?为什么单线程的redis比多线程的memched效率要高啊?

37、redis有什么数据类型都在哪些场景下使用啊?
38、reids的主从复制是怎么实现的redis的集群模式是如何实现的呢redis的key是如何寻址的啊?
39、使用redis如何设计分布式锁?使用zk可以吗?如何实现啊这两种哪个效率更高啊?
40、知道redis的持久化吗都有什么缺点优点啊? ?具体底层实现呢?
持久化有两种方案:RDB和AOF
RDB:
优点:最大化发挥redis的性能,主进程不需要进行任何I/O操作,只需要派生一个子进程来处理,文件非常紧凑,恢复数据的效率高。
缺点:数据恢复时一致性和完整性较差,因为也许最后一次备份前就宕机了,那么在最后一次备份到宕机中间的数据是不会存在的。
AOF:
优点:能保持数据的一致性和完整性。
缺点:AOF文件比RDB文件大,在读取过程中,会比RDB更慢一些。
底层实现
RDB:是在达到指定的时间或者操作次数后,自动将在内存中的数据写入磁盘
AOF:是日志形式,当数据写入内存中的时候,在日志文件下记录下所有写操作。

41、redis过期策略都有哪些LRU 写一下java版本的代码吧?
3种过期策略
1. 定时删除
含义:在设置key的过期时间的同时,为该key创建一个定时器,让定时器在key的过期时间来临时,对key进行删除
优点:保证内存被尽快释放
缺点:
若过期key很多,删除这些key会占用很多的CPU时间,在CPU时间紧张的情况下,CPU不能把所有的时间用来做要紧的事儿,还需要去花时间删除这些key
定时器的创建耗时,若为每一个设置过期时间的key创建一个定时器(将会有大量的定时器产生),性能影响严重
没人用
2. 惰性删除
含义:key过期的时候不删除,每次从数据库获取key的时候去检查是否过期,若过期,则删除,返回null。
优点:删除操作只发生在从数据库取出key的时候发生,而且只删除当前key,所以对CPU时间的占用是比较少的,而且此时的删除是已经到了非做不可的地步(如果此时还不删除的话,我们就会获取到了已经过期的key了)
缺点:若大量的key在超出超时时间后,很久一段时间内,都没有被获取过,那么可能发生内存泄露(无用的垃圾占用了大量的内存)
3. 定期删除
含义:每隔一段时间执行一次删除(在redis.conf配置文件设置hz,1s刷新的频率)过期key操作
优点:
通过限制删除操作的时长和频率,来减少删除操作对CPU时间的占用–处理"定时删除"的缺点
定期删除过期key–处理"惰性删除"的缺点
缺点
在内存友好方面,不如"定时删除"
在CPU时间友好方面,不如"惰性删除"

redis 过期策略是:定期删除+惰性删除。

    redis 内存淘汰机制有以下几个:
    (1)noeviction: 拒绝写操作, 读、删除可以正常使用。默认策略,不建议使用;
    (2)allkeys-lru: 移除最近最少使用的key,最常用的策略;
    (3)allkeys-random:随机删除某个key,不建议使用;
    (4)volatile-lru:在设置了过期时间的key中,移除最近最少使用的key,不建议使用;
    (5)volatile-random:在设置了过期时间的key中,随机删除某个key,不建议使用;
    (6)volatile-ttl: 在设置了过期时间的key中,把最早要过期的key优先删除。

42、说一下dubbo的实现过程注册中心挂了可以继续通信吗?
可以,因为刚开始初始化的时候,消费者会将提供者的地址等信息拉取到本地缓存,所以注册中心挂了可以继续通信。

43、dubbo支持哪些序列化协议?hessian 说一下hessian的数据结构PB知道吗为啥PB效率是最高的啊?
dubbo 支持不同的通信协议
dubbo 协议 : 默认就是走 dubbo 协议,单一长连接,进行的是 NIO 异步通信,基于 hessian 作为序列化协议。使用的场景是:传输数据量小(每次请求在 100kb 以内),但是并发量很高。
rmi 协议 : 走 Java 二进制序列化,多个短连接,适合消费者和提供者数量差不多的情况,适用于文件的传输,一般较少用。
hessian 协议 : 走 hessian 序列化协议,多个短连接,适用于提供者数量比消费者数量还多的情况,适用于文件的传输,一般较少用。
http 协议 : 走 json 序列化。
webservice : 走 SOAP 文本序列化。

    dubbo 支持的序列化协议
dubbo 支持 hession、Java 二进制序列化、json、SOAP 文本序列化多种序列化协议。但是 hessian 是其默认的序列化协议。

    Hessian 的数据结构
    Hessian 的对象序列化机制有 8 种原始类型:
    原始二进制数据
    boolean
    64-bit date(64 位毫秒值的日期)
    64-bit double
    32-bit int
    64-bit long
    null
    UTF-8 编码的 string
    另外还包括 3 种递归类型:
    list for lists and arrays
    map for maps and dictionaries
    object for objects
    还有一种特殊的类型:
    ref:用来表示对共享对象的引用。

  为什么 PB 的效率是最高的?
可能有一些同学比较习惯于 JSON or XML 数据存储格式,对于 Protocal Buffer 还比较陌生。Protocal Buffer 其实是 Google 出品的一种轻量并且高效的结构化数据存储格式,性能比 JSON、XML 要高很多。其实 PB 之所以性能如此好,主要得益于两个:第一,它使用 proto 编译器,自动进行序列化和反序列化,速度非常快,应该比 XML 和 JSON 快上了 20~100 倍;第二,它的数据压缩效果好,就是说它序列化后的数据量体积小。因为体积小,传输起来带宽和速度上会有优化。

44、知道netty吗’netty可以干嘛呀NIO,BIO,AIO 都是什么啊有什么区别啊?
45、dubbo复制均衡策略和高可用策略都有哪些啊动态代理策略呢?
46、为什么要进行系统拆分啊拆分不用dubbo可以吗’dubbo和thrift什么区别啊?
47、为什么使用消息队列啊消息队列有什么优点和缺点啊?
48、如何保证消息队列的高可用啊如何保证消息不被重复消费啊
49、kafka ,activemq,rabbitmq ,rocketmq都有什么优点,缺点啊?
50、如果让你写一个消息队列,该如何进行架构设计啊?说一下你的思路
51、说一下TCP 'IP四层?

52、http的工作流程?? ?http1.0 http1.1http2.0 具体哪些区别啊?
http的工作流程:
1)地址解析,需要域名系统DNS解析域名localhost.com,得主机的IP地址
2)封装HTTP请求数据包
3)封装成TCP包,建立TCP连接(TCP的三次握手)
4)客户机发送请求命令
5)服务器响应
6)服务器关闭TCP连接。如果浏览器或者服务器在其头信息加入了这行代码 Connection:keep-alive TCP连接在发送后将仍然保持打开状态,于是,浏览器可以继续通过相同的连接发送请求。保持连接节省了为每个请求建立新连接所需的时间,还节约了网络带宽。

    HTTP1.0 HTTP1.1主要区别
    1. 长连接:HTTP 1.0需要使用keep-alive参数来告知服务器端要建立一个长连接,而HTTP1.1默认支持长连接。
    2. 节约带宽:HTTP1.1支持只发送header信息(不带任何body信息),如果服务器认为客户端有权限请求服务器,则返回100,否则返回401。客户端如果接受到100,才开始把请求body发送到服务器。
3. HOST域:现在可以web server例如tomat,设置虚拟站点是非常常见的,也即是说,web server上的多个虚拟站点可以共享同一个ip和端口。HTTP1.0是没有host域的,HTTP1.1才支持这个参数。

    HTTP1.1 HTTP 2.0主要区别
    1. 多路复用 HTTP2.0使用了(类似epoll)多路复用的技术,做到同一个连接并发处理多个请求,而且并发请求的数量比HTTP1.1大了好几个数量级。当然HTTP1.1也可以多建立几个TCP连接,来支持处理更多并发的请求,但是创建TCP连接本身也是有开销的。
    2. 数据压缩 HTTP1.1不支持header数据的压缩,HTTP2.0使用HPACK算法对header的数据进行压缩,这样数据体积小了,在网络上传输就会更快。
    3. 服务器推送 意思是说,当我们对支持HTTP2.0的web server请求数据的时候,服务器会顺便把一些客户端需要的资源一起推送到客户端,免得客户端再次创建连接发送请求到服务器端获取。这种方式非常合适加载静态资源。

53、TCP三次握手,四层分手的工作流程画一下流程图为什么不是四次五次或者二次啊?
54、画一下https的工作流程?具体如何实现啊?如何防止被抓包啊?
55、源码中所用到的经典设计思想及常用设计模式
56、系统架构如何选择合适日志技术(log4j、log4j2、slf4j、jcl…….)
57、springAOP的原理,springAOP和Aspectj的关系,springAOP的源码问题
58、dubbo框架的底层通信原理
59、RPC通信原理,分布式通信原理
60、如何利用springCloud来架构微服务项目
61、springMVC的底层原理、如何从源码来分析其原理
62、mybaits的底层实现原理,如何从源码来分析mybaits
63、mysql的索引原理,索引是怎么实现的
64、索引的底层算法、如何正确使用、优化索引
65、zk原理知道吗zk都可以干什么Paxos算法知道吗?说一下原理和实现?
66、如果让你写一个消息队列,该如何进行架构设计啊?说一下你的思路
67、分布式事务知道吗? 你们怎么解决的?
68、请问你做过哪些JVM优化?使用什么方法达到什么效果?

java基础
Arrays.sort实现原理和Collection实现原理
foreach和while的区别(编译之后)
线程池的种类,区别和使用场景
分析线程池的实现原理和线程的调度过程
线程池如何调优
线程池的最大线程数目根据什么确定
动态代理的几种方式
HashMap的并发问题
了解LinkedHashMap的应用吗
反射的原理,反射创建类实例的三种方式是什么?
cloneable接口实现原理,浅拷贝or深拷贝
Java NIO使用
hashtable和hashmap的区别及实现原理,hashmap会问到数组索引,hash碰撞怎么解决
arraylist和linkedlist区别及实现原理
反射中,Class.forName和ClassLoader区别
String,Stringbuffer,StringBuilder的区别?
有没有可能2个不相等的对象有相同的hashcode
简述NIO的最佳实践,比如netty,mina
TreeMap的实现原理

JVM相关
类的实例化顺序,比如父类静态数据,构造函数,字段,子类静态数据,构造函数,字段,他们的执行顺序
JVM内存分代
Java 8的内存分代改进
JVM垃圾回收机制,何时触发MinorGC等操作
jvm中一次完整的GC流程(从ygc到fgc)是怎样的,重点讲讲对象如何晋升到老年代,几种主要的jvm参数等
你知道哪几种垃圾收集器,各自的优缺点,重点讲下cms,g1
新生代和老生代的内存回收策略
Eden和Survivor的比例分配等
深入分析了Classloader,双亲委派机制
JVM的编译优化
对Java内存模型的理解,以及其在并发中的应用
指令重排序,内存栅栏等
OOM错误,stackoverflow错误,permgen space错误
JVM常用参数
tomcat结构,类加载器流程
volatile的语义,它修饰的变量一定线程安全吗
g1和cms区别,吞吐量优先和响应优先的垃圾收集器选择
说一说你对环境变量classpath的理解?如果一个类不在classpath下,为什么会抛出ClassNotFoundException异常,如果在不改变这个类路径的前期下,怎样才能正确加载这个类?
说一下强引用、软引用、弱引用、虚引用以及他们之间和gc的关系

JUC/并发相关
ThreadLocal用过么,原理是什么,用的时候要注意什么
Synchronized和Lock的区别
synchronized 的原理,什么是自旋锁,偏向锁,轻量级锁,什么叫可重入锁,什么叫公平锁和非公平锁
concurrenthashmap具体实现及其原理,jdk8下的改版
用过哪些原子类,他们的参数以及原理是什么
cas是什么,他会产生什么问题(ABA问题的解决,如加入修改次数、版本号)
如果让你实现一个并发安全的链表,你会怎么做
简述ConcurrentLinkedQueue和LinkedBlockingQueue的用处和不同之处
简述AQS的实现原理
countdowlatch和cyclicbarrier的用法,以及相互之间的差别?
concurrent包中使用过哪些类?分别说说使用在什么场景?为什么要使用?
LockSupport工具
Condition接口及其实现原理
Fork/Join框架的理解
jdk8的parallelStream的理解
分段锁的原理,锁力度减小的思考

Spring
Spring AOP与IOC的实现原理
Spring的beanFactory和factoryBean的区别
为什么CGlib方式可以对接口实现代理?
RMI与代理模式
Spring的事务隔离级别,实现原理
对Spring的理解,非单例注入的原理?它的生命周期?循环注入的原理,aop的实现原理,说说aop中的几个术语,它们是怎么相互工作的?
Mybatis的底层实现原理
MVC框架原理,他们都是怎么做url路由的
spring boot特性,优势,适用场景等
quartz和timer对比
spring的controller是单例还是多例,怎么保证并发的安全

分布式相关
Dubbo的底层实现原理和机制
描述一个服务从发布到被消费的详细过程
分布式系统怎么做服务治理
接口的幂等性的概念
消息中间件如何解决消息丢失问题
Dubbo的服务请求失败怎么处理
重连机制会不会造成错误
对分布式事务的理解
如何实现负载均衡,有哪些算法可以实现?
Zookeeper的用途,选举的原理是什么?
数据的垂直拆分水平拆分。
zookeeper原理和适用场景
zookeeper watch机制
redis/zk节点宕机如何处理
分布式集群下如何做到唯一序列号
如何做一个分布式锁
用过哪些MQ,怎么用的,和其他mq比较有什么优缺点,MQ的连接是线程安全的吗
MQ系统的数据如何保证不丢失
列举出你能想到的数据库分库分表策略;分库分表后,如何解决全表查询的问题。

算法&数据结构&设计模式
海量url去重类问题(布隆过滤器)
数组和链表数据结构描述,各自的时间复杂度
二叉树遍历
快速排序
BTree相关的操作
在工作中遇到过哪些设计模式,是如何应用的
hash算法的有哪几种,优缺点,使用场景
什么是一致性hash
paxos算法
在装饰器模式和代理模式之间,你如何抉择,请结合自身实际情况聊聊
代码重构的步骤和原因,如果理解重构到模式?

数据库
MySQL InnoDB存储的文件结构
索引树是如何维护的?
数据库自增主键可能的问题
MySQL的几种优化
mysql索引为什么使用B+树
数据库锁表的相关处理
索引失效场景
高并发下如何做到安全的修改同一行数据,乐观锁和悲观锁是什么,INNODB的行级锁有哪2种,解释其含义
数据库会死锁吗,举一个死锁的例子,mysql怎么解决死锁

Redis&缓存相关
Redis的并发竞争问题如何解决了解Redis事务的CAS操作吗
缓存机器增删如何对系统影响最小,一致性哈希的实现
Redis持久化的几种方式,优缺点是什么,怎么实现的
Redis的缓存失效策略
缓存穿透的解决办法
redis集群,高可用,原理
mySQL里有2000w数据,redis中只存20w的数据,如何保证redis中的数据都是热点数据
用Redis和任意语言实现一段恶意登录保护的代码,限制1小时内每用户Id最多只能登录5次
redis的数据淘汰策略

网络相关
http1.0和http1.1有什么区别
TCP/IP协议
TCP三次握手和四次挥手的流程,为什么断开连接要4次,如果握手只有两次,会出现什么
TIME_WAIT和CLOSE_WAIT的区别
说说你知道的几种HTTP响应码
当你用浏览器打开一个链接的时候,计算机做了哪些工作步骤
TCP/IP如何保证可靠性,数据包有哪些数据组成
长连接与短连接
Http请求get和post的区别以及数据包格式
简述tcp建立连接3次握手,和断开连接4次握手的过程;关闭连接时,出现TIMEWAIT过多是由什么原因引起,是出现在主动断开方还是被动断开方。

其他
maven解决依赖冲突,快照版和发行版的区别
Linux下IO模型有几种,各自的含义是什么
实际场景问题,海量登录日志如何排序和处理SQL操作,主要是索引和聚合函数的应用
实际场景问题解决,典型的TOP K问题
线上bug处理流程
如何从线上日志发现问题
linux利用哪些命令,查找哪里出了问题(例如io密集任务,cpu过度)
场景问题,有一个第三方接口,有很多个线程去调用获取数据,现在规定每秒钟最多有10个线程同时调用它,如何做到。
用三个线程按顺序循环打印abc三个字母,比如abcabcabc。
常见的缓存策略有哪些,你们项目中用到了什么缓存系统,如何设计的
设计一个秒杀系统,30分钟没付款就自动关闭交易(并发会很高)
请列出你所了解的性能测试工具
后台系统怎么防止请求重复提交?

XXP7 笔试题

  1. junit 用法,before,beforeClass,after, afterClass 的执行顺序
  2. 分布式锁
  3. nginx 的请求转发算法,如何配置根据权重转发
  4. 用 hashmap 实现 redis 有什么问题(死锁,死循环,可用 ConcurrentH
    ashmap)
  5. 线程的状态
  6. 线程的阻塞的方式
  7. sleep 和 wait 的区别
  8. hashmap 的底层实现
  9. 一万个人抢 100 个红包,如何实现(不用队列),如何保证 2 个人不能抢
    到同一个红包,可用分布式锁
  10. java 内存模型,垃圾回收机制,不可达算法
  11. 两个 Integer 的引用对象传给一个 swap 方法在方法内部交换引用,返回
    后,两个引用的值是否会发现变化
  12. aop 的底层实现,动态代理是如何动态,假如有 100 个对象,如何动态
    的为这 100 个对象代理
  13. 是否用过 maven install。 maven test。git(make install 是安装本
    地 jar 包)
  14. tomcat 的各种配置,如何配置 docBase
  15. spring 的 bean 配置的几种方式
  16. web.xml 的配置
  17. spring 的监听器。
  18. zookeeper 的实现机制,有缓存,如何存储注册服务的
  19. IO 会阻塞吗?readLine 是不是阻塞的
  20. 用过 spring 的线程池还是 java 的线程池?
  21. 字符串的格式化方法 (20,21 这两个问题问的太低级了)
  22. 时间的格式化方法
  23. 定时器用什么做的
  24. 线程如何退出结束
  25. java 有哪些锁?乐观锁 悲观锁 synchronized 可重入锁 读写锁,用过 r
    eentrantlock 吗?reentrantlock 与 synmchronized 的区别
  26. ThreadLocal 的使用场景
  27. java 的内存模型,垃圾回收机制
  28. 为什么线程执行要调用 start 而不是直接 run(直接 run,跟普通方法没
    什么区别,先调 start,run 才会作为一个线程方法运行)
  29. qmq 消息的实现机制(qmq 是去哪儿网自己封装的消息队列)
  30. 遍历 hashmap 的三种方式
  31. jvm 的一些命令
  32. memcache 和 redis 的区别
  33. mysql 的行级锁加在哪个位置
  34. ConcurrentHashmap 的锁是如何加的?是不是分段越多越好
  35. myisam 和 innodb 的区别(innodb 是行级锁,myisam 是表级锁)
  36. mysql 其他的性能优化方式
  37. linux 系统日志在哪里看
  38. 如何查看网络进程
  39. 统计一个整数的二进制表示中 bit 为 1 的个数
  40. jvm 内存模型,java 内存模型
  41. 如何把 java 内存的数据全部 dump 出来
  42. 如何手动触发全量回收垃圾,如何立即触发垃圾回收
  43. hashmap 如果只有一个写其他全读会出什么问题
  44. git rebase
  45. mongodb 和 hbase 的区别
  46. 如何解决并发问题
  47. volatile 的用途
  48. java 线程池(好像之前我的理解有问题)
  49. mysql 的 binlog
  50. 代理模式
  51. mysql 是如何实现事务的
  52. 读写分离何时强制要读主库,读哪个从库是通过什么方式决定的,从库的
    同步 mysql 用的什么方式
  53. mysql 的存储引擎
  54. mysql 的默认隔离级别,其他隔离级别
  55. 将一个链表反转(用三个指针,但是每次只发转一个)
  56. spring Aop 的实现原理,具体说说
  57. 何时会内存泄漏,内存泄漏会抛哪些异常
  58. 是否用过 Autowire 注解
  59. spring 的注入 bean 的方式
  60. sql 语句各种条件的执行顺序,如 select, where, order by, grou
    p by
  61. select xx from xx where xx and xx order by xx limit xx; 如
    何优化这个(看 explain)
  62. 四则元算写代码
  63. 统计 100G 的 ip 文件中出现 ip 次数最多的 100 个 ip
  64. zookeeper 的事物,结点,服务提供方挂了如何告知消费方
  65. 5 台服务器如何选出 leader(选举算法)
  66. 适配器和代理模式的区别
  67. 读写锁
  68. static 加锁
  69. 事务隔离级别
  70. 门面模式,类图(外观模式)
  71. mybatis 如何映射表结构
  72. 二叉树遍历
  73. 主从复制
  74. mysql 引擎区别
  75. 静态内部类加载到了哪个区?方法区
  76. class 文件编译后加载到了哪
  77. web 的 http 请求如何整体响应时间变长导致处理的请求数变少,该如何
    处理?用队列,当处理不了那么多 http 请求时将请求放到队列
    中慢慢处理,web 如何实现队列
  78. 线程安全的单例模式
  79. 快速排序性能考虑
  80. volatile 关键字用法
  81. 求表的 size,或做数据统计可用什么存储引擎
  82. 读多写少可用什么引擎
  83. 假如要统计多个表应该用什么引擎
  84. concurrenhashmap 求 size 是如何加锁的,如果刚求完一段后这段发生
    了变化该如何处理
  85. 1000 个苹果放 10 个篮子,怎么放,能让我拿到所有可能的个数
  86. 可重入的读写锁,可重入是如何实现的?
  87. 是否用过 NIO
  88. java 的 concurrent 包用过没
  89. sting s=new string(“abc”)分别在堆栈上新建了哪些对象
  90. java 虚拟机的区域分配,各区分别存什么
  91. 分布式事务(JTA)
  92. threadlocal 使用时注意的问题(ThreadLocal 和 Synchonized 都用于
    解决多线程并发访问。但是 ThreadLocal 与 synchronized 有本质的区别。s
    ynchronized 是利用锁的机制,使变量或代码块在某一时该只能被一个线程访
    问。而 ThreadLocal 为每一个线程都提供了变量的副本,使得每个线程在某
    一时间访问到的并不是同一个对象,这样就隔离了多个线程对数据的数据共
    享。而 Synchronized 却正好相反,它用于在多个线程间通信时能够获得数据
    共享)
  93. java 有哪些容器(集合,tomcat 也是一种容器)
  94. 二分查找算法
  95. myisam 的优点,和 innodb 的区别
  96. redis 能存哪些类型
  97. http 协议格式,get 和 post 的区别
  98. 可重入锁中对应的 wait 和 notify
  99. redis 能把内存空间交换进磁盘中吗(这个应该是可以的,但是那个面试官
    非跟我说不可以)
  100. java 线程池中基于缓存和基于定长的两种线程池,当请求太多时分别是如
    何处理的?定长的事用的队列,如果队列也满了呢?交换进磁盘?基于缓存的
    线程池解决方法呢?
  101. synchronized 加在方法上用的什么锁
  102. 可重入锁中的 lock 和 trylock 的区别
  103. innodb 对一行数据的读会枷锁吗?不枷锁,读实际读的是副本
  104. redis 做缓存是分布式存的?不同的服务器上存的数据是否重复?guava
    cache 呢?是否重复?不同的机器存的数据不同
  105. 用 awk 统计一个 ip 文件中 top10
  106. 对表做统计时可直接看 schema info 信息,即查看表的系统信息
  107. mysql 目前用的版本
  108. 公司经验丰富的人给了什么帮助?(一般 boss 面会问这些)
  109. 自己相对于一样的应届生有什么优势
  110. 自己的好的总结习惯给自己今后的工作带了什么帮助,举例为证
  111. 原子类,线程安全的对象,异常的处理方式
  112. 4 亿个 int 数,如何找出重复的数(用 hash 方法,建一个 2 的 32 次
    方个 bit 的 hash 数组,每取一个 int 数,可 hash 下 2 的 32 次方找到它在 h
    ash 数组中的位置,然后将 bit 置 1 表示已存在)
  113. 4 亿个 url,找出其中重复的(考虑内存不够,通过 hash 算法,将 url
    分配到 1000 个文件中,不同的文件间肯定就不会重复了,再分别找出重复
    的)
    有 1 万个数组,每个数组有 1000 个整数,每个数组都是降序的,从中找出
    最大的 N 个数,N<1000
  114. LinkedHashmap 的底层实现
  115. 类序列化时类的版本号的用途,如果没有指定一个版本号,系统是怎么处理的?如果加了字段会怎么样?
  116. Override 和 Overload 的区别,分别用在什么场景
  117. java 的反射是如何实现的

一些小建议
可以去leetcode上刷题换换思路。
八大排序算法一定要手敲一遍(快排,堆排尤其重要)。
了解一些新兴的技术。
面试之后面试官都会问你有没有什么问题,千万不要没问题,也别傻乎乎的问一些敏感问题。
了解你要面试的公司的产品及竞争产品。

HashMap在Java1.7与1.8中的区别
在JDK1.7之前

使用一个Entry数组来存储数据,用hash()和indexFor(int h, intlength)来决定key会被放到数组里的位置,如果hashcode相同,或者hashcode取模后的结果相同(hash collision),那么这些key会被定位到Entry数组的同一个格子里,这些key会形成一个链表。

在hashcode特别差的情况下,比方说所有key的hashcode都相同,这个链表可能会很长,那么put/get操作都可能需要遍历这个链表,也就是说时间复杂度在最差情况下会退化到O(n)。

在JDK1.8中

使用一个Node数组来存储数据,但这个Node可能是链表结构,也可能是红黑树结构。如果插入的key的hashcode相同,那么这些key也会被定位到Node数组的同一个格子里。

如果同一个格子里的key不超过8个,使用链表结构存储。

如果超过了8个,那么会调用treeifyBin函数,将链表转换为红黑树。

那么即使hashcode完全相同,由于红黑树的特点,查找某个特定元素,也只需要O(log n)的开销,也就是说put/get的操作的时间复杂度最差只有O(log n)

上午面试内容:

  1. eureka和zookeeper区别
  2. dubbo和springcloud区别
  3. 你们怎么做到服务治理和服务熔断
  4. 你们怎么做的分布式事务
  5. springboot特点,怎么加载的配置信息
  6. 项目中有很多注解配置类,怎么设置加载的顺序
  7. 说一下mybatis一级缓存二级缓存
  8. springcloud你们怎么做的负载均衡
  9. 微服务你们用的哪个日志框架?怎么查看的日志信息
  10. zookeeper选举过程
  11. dubbo怎么做的负载均衡、springcloud怎么做的负载均衡

下午面试内容

  1. 介绍你最拿手的一个项目(画流程,让面试官看懂)

  2. jvm各区比例大小

    1. 堆分为新生代和老年代,默认情况下新生代占堆的1/3,老年代占堆的2/3。
    2. 新生代中 eden区:80% Survivor from(s0):10% Survivor to(s1):%10
  3. 对象怎样从endn区到的s区,eden区会不会被回收
    一般情况下,新创建的对象都会被分配到Eden区(一些大对象特殊处理),这些对象经过第一次Minor GC后,如果仍然存活,将会被移到Survivor区。对象在Survivor区中每熬过一次Minor GC,年龄就会增加1岁,当它的年龄增加到一定程度时(15次),就会被移动到年老代中。
    eden区会被回收。

  4. 我想知道HashMap key怎么定位的具体的数组
    主要这两个函数
    1).
    static final int hash(Object key) {
    int h;
    return (key == null) ? 0 : (h = key.hashCode()) ^ (h >>> 16);
    }
    2). tab[(n - 1) & hash]

    解析:
    获取key的散列表,即hash值,显然hash值是int类型,最高32位。如果仅仅通过hash值定位数组的索引,将有10亿的范围。这个范围太大,以至于内存根本放不下。所以必须对它进行处理。

    (n - 1) & hash 通过这个表达式就可以处理(n = tab.length)。数组的长度是2的n次方,这样的好处是(n-1)的二进制表达式变为…000…000111…111,最后几位都是1,这样和hash进行与操作时只会保留hash值最后面几位二进制位,大小在0-(n-1),这刚好就是数组的索引。

    put:
    public V put(K key, V value) {
    return putVal(hash(key), key, value, false, true);
    }

    static final int hash(Object key) {
    int h;
    return (key == null) ? 0 : (h = key.hashCode()) ^ (h >>> 16);
    }

    final V putVal(int hash, K key, V value, boolean onlyIfAbsent,
    boolean evict) {
    Node<K,V>[] tab; Node<K,V> p; int n, i;
    if ((tab = table) == null || (n = tab.length) == 0)
    n = (tab = resize()).length;
    if ((p = tab[i = (n - 1) & hash]) == null)
    tab[i] = newNode(hash, key, value, null);
    else {
    Node<K,V> e; K k;
    if (p.hash == hash &&
    ((k = p.key) == key || (key != null && key.equals(k))))
    e = p;
    else if (p instanceof TreeNode)
    e = ((TreeNode<K,V>)p).putTreeVal(this, tab, hash, key, value);
    else {
    for (int binCount = 0; ; ++binCount) {
    if ((e = p.next) == null) {
    p.next = newNode(hash, key, value, null);
    if (binCount >= TREEIFY_THRESHOLD - 1) // -1 for 1st
    treeifyBin(tab, hash);
    break;
    }
    if (e.hash == hash &&
    ((k = e.key) == key || (key != null && key.equals(k))))
    break;
    p = e;
    }
    }
    if (e != null) { // existing mapping for key
    V oldValue = e.value;
    if (!onlyIfAbsent || oldValue == null)
    e.value = value;
    afterNodeAccess(e);
    return oldValue;
    }
    }
    ++modCount;
    if (++size > threshold)
    resize();
    afterNodeInsertion(evict);
    return null;
    }

    get:
    public V get(Object key) {
    Node<K,V> e;
    return (e = getNode(hash(key), key)) == null ? null : e.value;
    }

    final Node<K,V> getNode(int hash, Object key) {
    Node<K,V>[] tab; Node<K,V> first, e; int n; K k;
    if ((tab = table) != null && (n = tab.length) > 0 &&
    (first = tab[(n - 1) & hash]) != null) {
    if (first.hash == hash && // always check first node
    ((k = first.key) == key || (key != null && key.equals(k))))
    return first;
    if ((e = first.next) != null) {
    if (first instanceof TreeNode)
    return ((TreeNode<K,V>)first).getTreeNode(hash, key);
    do {
    if (e.hash == hash &&
    ((k = e.key) == key || (key != null && key.equals(k))))
    return e;
    } while ((e = e.next) != null);
    }
    }
    return null;
    }

  5. 我有个16长度的数据,又不想扩容,hashmap长度定义多少

下午面试内容

  1. 介绍你最拿手的一个项目(画流程,让面试官看懂)
  2. jvm各区比例大小
  3. 对象怎样从endn区到的s区,eden区会不会被回收
  4. 我想知道HashMap key怎么定位的具体的数组
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值