答案不全,欢迎补充订正~
Java基础
1、List 和 Set 的区别~List允许重复,有序容器,按照存放顺序存放,允许多个null值。
~Set不允许重复,无序容器,只允许有一个null值。
2、HashSet 是如何保证不重复的~HashSet的构造方法就是在内部实例化了一个HashMap对象,在存储数据时将值作为map的key,value则为一个finale修饰的变量,因为HashMap不允许有重复的key,所以实现了HashSet无重复值。
3、HashMap 是线程安全的吗,为什么不是线程安全的(最好画图说明多线程环境下不安全)?~线程不安全,put方法和resize 都是非同步方法。
4、HashMap 的扩容过程~在扩容过程中,会新生成一个新的容量的数组,然后对原数组的所有键值对重新进行计算和写入新的数组,之后指向新生成的数组。
5、HashMap 1.7 与 1.8 的 区别,说明 1.8 做了哪些优化,如何优化的?~ JDK1.8引入红黑树大程度优化了HashMap的性能。当链表的长度大于8时,转换为红黑树的结构。
6、final finally finalize~1-final是一个修饰符,可以修饰变量,方法和类,如果final修饰变量,意味着该变量的值在初始化之后就不能被改变。
2-finally是一个关键字,与try和catch一起用于异常的处理,finally块一定会被执行,无论在try块中是否发生异常。
3-finallize方法是在对象被回收之前调用的方法,给对象自己最后一个复活的机会,但是什么时候调用finallize没有保证。
7、强引用 、软引用、 弱引用、虚引用~1-强引用:如果一个对象具有强引用,它就不会被垃圾回收器回收,即使当前内存空间不足,JVM也不会回收它,而是抛出OutOfMemoryError,使程序异常终止;2-软引用:在使用软引用时,如果内存的空间足够,软应用就能继续被使用,而不会被回收,只有在内存不足的时候才会被回收;3-弱引用:具有弱引用的对象拥有的生命周期更短暂,因为当JVM一旦发现弱引用对象,无论当前内存空间是否充足,都会将弱引用回收;
4-虚引用:如果一个对象仅持有虚引用,那么它相当于没有引用,在任何时候都有可能被垃圾回收。
8、Java反射
~Reflection(反射)是Java被视为动态语言的关键,反射机制允许程序在执行期借助于Reflection API取得任何类的內部信息,并能直接操作任意对象的内部属性及方法。Java反射机制主要提供了以下功能:1-在运行时构造任意一个类的对象;2-在运行时获取任意一个类所具有的成员变量和方法;3-在运行时调用任意一个对象的方法(属性);4-生成动态代理;Java 并发
1、synchronized 的实现原理以及锁优化?~Java虚拟机中的同步(Synchronization)都是基于进入和退出Monitor对象实现,无论是显示同步(同步代码块)还是隐式同步(同步方法)都是如此。
JDK1.6之后JVM官方对锁做了较大优化:
引入了:
锁粗化(Lock Coarsening)
锁消除(Lock Elimination)
适应性自旋(Adaptive Spinning)
同时增加了两种锁的状态:
偏向锁(Biased Locking)
轻量锁(Lightweight Locking)
详细:
参考收藏笔记
2、volatile 的实现原理?
~1.将当前处理器缓存行的数据会写回到系统内存。
2.这个写回内存的操作会引起在其他CPU里缓存了该内存地址的数据无效。
3、Java 的信号灯?
~Semaphore是Java1.5之后提供的一种同步工具,Semaphore可以维护访问自身线程个数,并提供了同步机制。使用Semaphore可以控制同时访问资源的线程个数,通过 acquire() 获取一个许可,如果没有就等待,而release() 释放一个许可。
4、synchronized 在静态方法和普通方法的区别?
~synchronized修饰不加static的方法,锁是加在单个对象上,不同的对象没有竞争关系;修饰加了static的方法,锁是加载类上,这个类所有的对象竞争一把锁。5、怎么实现所有线程在等待某个事件的发生才会去执行?~java里面实现这个有两个办法,countdownlatch和cyclicbarrier。
cyclicbarrier可以重复使用,它允许一组线程相互等待,直到达到某个公共屏障点。cyclicbarrier不会阻塞主线程,只会阻塞子线程。
countdownlatch不可以重复使用,会阻塞主线程。主线程调用await方法,主线程阻塞。子线程调用countdown方法,触发计数。countdownlatch内部是实现了AQS,初始化的时候,new CountDownLatch(n);将AQS的state设置为n。
6、CAS?CAS 有什么缺陷,如何解决?~CAS(Compare-and-Swap),即比较并替换,是一种实现并发算法时常用到的技术。
缺陷:
1-循环时间长开销很大。
getAndAddInt方法执行时,只有完成覆盖才会调出循环,如果CAS失败,会一直进行尝试。如果CAS长时间一直不成功,可能会给CPU带来很大的开销。
2-只能保证一个共享变量的原子操作。
当对一个共享变量执行操作时,我们可以使用循环CAS的方式来保证原子操作,但是对多个共享变量操作时,循环CAS就无法保证操作的原子性,这个时候就可以用锁来保证原子性。
3-ABA问题。
如果内存地址V初次读取的值是A,并且在准备赋值的时候检查到它的值仍然为A,如果在这段期间它的值曾经被改成了B,后来又被改回为A,那CAS操作就会误认为它从来没有被改变过。这个漏洞称为CAS操作的“ABA”问题,Java并发包为了解决这个问题,提供了一个带有标记的原子引用类“AtomicStampedReference”,它可以通过控制变量值的版本来保证CAS的正确性。
7、synchronized 和 lock 有什么区别?~1-Lock不是Java语言内置的,synchronized是Java语言的关键字,因此是内置特性。Lock是一个类,通过这个类可以实现同步访问;
2-Lock和synchronized有一点非常大的不同,采用synchronized不需要用户去手动释放锁,当synchronized方法或者synchronized代码块执行完之后,系统会自动让线程释放对锁的占用;而Lock则必须要用户去手动释放锁,如果没有主动释放锁,就有可能导致出现死锁现象。
8、Hashtable 是怎么加锁的 ?~ Hashtable ht = Hashtable.Synchronized(new Hashtable());
9、HashMap 的并发问题?~1-多线程put后可能导致get死循环
2-多线程put的时候可能导致元素丢失
3-put非null元素后get出来的却是null
会造成的严重的cpu飙升问题,从而产生内存泄露。
10、ConcurrentHashMap 介绍?1.8 中为什么要用红黑树?~ConcurrentHashMap是在JDK 1.5上添加的并发收集类,用于替代基于哈希的同步映射实现,例如Hashtable和HashMap。他们的同步对手提供更好的性能和可扩展性,风险很小。
因为红黑树的性能特点,在大量 hashcode 值相同的时候,查找某个特定元素,也只是需要O(log n) 的开销。
11、AQS~AQS是AbustactQueuedSynchronizer的简称,它是一个Java提供的底层同步工具类,用一个int类型的变量表示同步状态,并提供了一系列的CAS操作来管理这个同步状态。AQS的主要作用是为Java中的并发同步组件提供统一的底层支持,例如ReentrantLock(可重入锁),CountdownLatch(闭锁)就是基于AQS实现的,用法是通过继承AQS实现其模版方法,然后将子类作为同步组件的内部类。
12、如何检测死锁?怎么预防死锁?~可以使用 jstack或者pstack 和 gdb 工具对死锁程序进行分析。
预防死锁的方法是通过设置某些限制条件,去破坏产生死锁的四个必要条件中的一个或者几个,以避免发生死锁。
由于互斥条件是非共享设备所必须的,不仅不能改变,还应该加以保证,因此,主要是破坏产生死锁的后三个条件。
1-破坏请求与保持条件:对一个进程在请求资源时,它不能持有不可剥夺资源。
2-破坏不可剥夺条件:对一个已经保持了某些不可剥夺资源的进程,提出新的资源请求而不能得到满足时,它必须释放已经保持的所有资源,待以后需要时再重新申请。
3-破坏循环等待条件:对系统所有资源类型进行线性排列,并赋予不同序号。规定每个进程必须按序号递增的顺序请求资源。
13、Java 内存模型?~Java内存模型(即Java Memory Model,简称JMM)本身是一种抽象的概念,并不真实存在,它描述的是一组规则或规范,通过这组规范定义了程序中各个变量(包括实例字段,静态字段和构成数组对象的元素)的访问方式。由于JVM运行程序的实体是线程,而每个线程创建时JVM都会为其创建一个工作内存(有些地方称为栈空间),用于存储线程私有的数据,而Java内存模型中规定所有变量都存储在主内存,主内存是共享内存区域,所有线程都可以访问,但线程对变量的操作(读取赋值等)必须在工作内存中进行,首先要将变量从主内存拷贝的自己的工作内存空间,然后对变量进行操作,操作完成后再将变量写回主内存,不能直接操作主内存中的变量,工作内存中存储着主内存中的变量副本拷贝,前面说过,工作内存是每个线程的私有数据区域,因此不同的线程间无法访问对方的工作内存,线程间的通信(传值)必须通过主内存来完成。
14、如何保证多线程下 i++ 结果正确?~1-使用循环CAS,实现i++原子操作
2-使用ReentrantLock 锁机制,实现i++原子操作
3-使用synchronized,实现i++原子操作
15、线程池的种类,区别和使用场景?~
1-newCachedThreadPool:
底层:返回ThreadPoolExecutor实例,corePoolSize为0;maximumPoolSize为Integer.MAX_VALUE;keepAliveTime为60L;unit为TimeUnit.SECONDS;workQueue为SynchronousQueue(同步队列)
通俗:当有新任务到来,则插入到SynchronousQueue中,由于SynchronousQueue是同步队列,因此会在池中寻找可用线程来执行,若有可以线程则执行,若没有可用线程则创建一个线程来执行该任务;若池中线程空闲时间超过指定大小,则该线程会被销毁。
适用:执行很多短期异步的小程序或者负载较轻的服务器
2-newFixedThreadPool:
底层:返回ThreadPoolExecutor实例,接收参数为所设定线程数量nThread,corePoolSize为nThread,maximumPoolSize为nThread;keepAliveTime为0L(不限时);unit为:TimeUnit.MILLISECONDS;WorkQueue为:new LinkedBlockingQueue<Runnable>() 无解阻塞队列
通俗:创建可容纳固定数量线程的池子,每隔线程的存活时间是无限的,当池子满了就不在添加线程了;如果池中的所有线程均在繁忙状态,对于新任务会进入阻塞队列中(无界的阻塞队列)
适用:执行长期的任务,性能好很多
3-newSingleThreadExecutor:
底层:FinalizableDelegatedExecutorService包装的ThreadPoolExecutor实例,corePoolSize为1;maximumPoolSize为1;keepAliveTime为0L;unit为:TimeUnit.MILLISECONDS;workQueue为:new LinkedBlockingQueue<Runnable>() 无解阻塞队列
通俗:创建只有一个线程的线程池,且线程的存活时间是无限的;当该线程正繁忙时,对于新任务会进入阻塞队列中(无界的阻塞队列)
适用:一个任务一个任务执行的场景
4-NewScheduledThreadPool:
底层:创建ScheduledThreadPoolExecutor实例,corePoolSize为传递来的参数,maximumPoolSize为Integer.MAX_VALUE;keepAliveTime为0;unit为:TimeUnit.NANOSECONDS;workQueue为:new DelayedWorkQueue() 一个按超时时间升序排序的队列
通俗:创建一个固定大小的线程池,线程池内线程存活时间无限制,线程池可以支持定时及周期性任务执行,如果所有线程均处于繁忙状态,对于新任务会进入DelayedWorkQueue队列中,这是一种按照超时时间排序的队列结构
适用:周期性执行任务的场景
16、分析线程池的实现原理和线程的调度过程?~说白了实现原理就是一个线程集合workerSet和一个阻塞队列workQueue。当用户向线程池提交一个任务(也就是线程)时,线程池会先将任务放入workQueue中。workerSet中的线程会不断的从workQueue中获取线程然后执行。当workQueue中没有任务的时候,worker就会阻塞,直到队列中有任务了就取出来继续执行。
17、线程池如何调优,最大数目如何确认?~设置最大线程数
对于给定硬件上的给定负载,最大线程数设置为多少最好呢?这个问题回答起来并不简单:它取决于负载特性以及底层硬件。特别是,最优线程数还与每个任务阻塞的频率有关。
假设JVM有4个CPU可用,很明显最大线程数至少要设置为4。的确,除了处理这些任务,JVM还有些线程要做其他的事,但是它们几乎从来不会占用一个完整的CPU,至于这个数值是否要大于4,则需要进行大量充分的测试。
有以下两点需要注意:
一旦服务器成为瓶颈,向服务器增加负载时非常有害的;
对于CPU密集型或IO密集型的机器增加线程数实际会降低整体的吞吐量;
设置最小线程数
一旦确定了线程池的最大线程数,就该确定所需的最小线程数了。大部分情况下,开发者会直截了当的将他们设置成同一个值。
将最小线程数设置为其他某个值(比如1),出发点是为了防止系统创建太多线程,以节省系统资源。指定一个最小线程数的负面影响相当小。如果第一次就有很多任务要执行,会有负面影响:这是线程池需要创建一个新线程。创建线程对性能不利,这也是为什么起初需要线程池的原因。
一般而言,对于线程数为最小值的线程池,一个新线程一旦创建出来,至少应该保留几分钟,以处理任何负载飙升。空闲时间应该以分钟计,而且至少在10分钟到30分钟之间,这样可以防止频繁创建线程。
线程池任务大小
等待线程池来执行的任务会被保存到某个队列或列表中;当池中有线程可以执行任务时,就从队列中拉出一个。这会导致不均衡:队列中任务的数量可能变得非常大。如果队列太大,其中的任务就必须等待很长时间,直到前面的任务执行完毕。
对于任务队列,线程池通常会限制其大小。但是这个值应该如何调优,并没有一个通用的规则。若要确定哪个值能带来我们需要的性能,测量我们的真实应用是唯一的途径。不管是哪种情况,如果达到了队列限制,再添加任务就会失败。ThreadPoolExecutor有一个rejectedExecution方法,用于处理这种情况,默认会抛出RejectedExecutionExecption。应用服务器会向用户返回某个错误:或者是HTTP状态码500,或者是Web服务器捕获异常错误,并向用户给出合理的解释消息—其中后者是最理想的。
设置ThreadPoolExecutor的大小
线程池的一般行为是这样的:创建时准备最小数目的线程,如果来了一个任务,而此时所有的线程都在忙碌,则启动一个新线程(一直到达到最大线程数),任务就会立即执行。否则,任务被加入到等待队列,如果队列中已经无法加入新任务,则拒接之。
根据所选任务队列的类型,ThreadPoolExecutor会决定何时会启动一个新线程。有以下三种可能:
SynchronousQueue
如果ThreadPoolExecutor搭配的是SynchronousQueue,则线程池的行为和我们预期的一样,它会考虑线程数:如果所有的线程都在忙碌,而且池中的线程数尚未达到最大,则会为新任务启动一个新线程。然而这个队列没办法保存等待的任务:如果来了一个任务,创建的线程数已经达到最大值,而且所有的线程都在忙碌,则新的任务都会被拒绝,所以如果是管理少量的任务,这是个不错的选择,对于其他的情况就不适合了。
无界队列
如果ThreadPoolExecutor搭配的是无界队列,如LinkedBlockingQueue,则不会拒绝任何任务(因为队列大小没有限制)。这种情况下,ThreadPoolExecutor最多仅会按照最小线程数创建线程,也就是说最大线程池大小被忽略了。如果最大线程数和最小线程数相同,则这种选择和配置了固定线程数的传统线程池运行机制最为接近。
有界队列
搭配了有界队列,如ArrayBlockingQueue的ThreadPoolExecutor会采用一个非常负责的算法。比如假定线程池的最小线程数为4,最大为8所用的ArrayBlockingQueue最大为10。随着任务到达并被放到队列中,线程池中最多运行4个线程(即最小线程数)。即使队列完全填满,也就是说有10个处于等待状态的任务,ThreadPoolExecutor也只会利用4个线程。
如果队列已满,而又有新任务进来,此时才会启动一个新线程,这里不会因为队列已满而拒接该任务,相反会启动一个新线程。新线程会运行队列中的第一个任务,为新来的任务腾出空间。
这个算法背后的理念是:该池大部分时间仅使用核心线程(4个),即使有适量的任务在队列中等待运行。这时线程池就可以用作节流阀。如果挤压的请求变得非常多,这时该池就会尝试运行更多的线程来清理;这时第二个节流阀—最大线程数就起作用了。
18、ThreadLocal原理,用的时候需要注意什么?~ThreadLoal 变量,它的基本原理是,同一个 ThreadLocal 所包含的对象(对ThreadLocal< String >而言即为 String 类型变量),在不同的 Thread 中有不同的副本(实际是不同的实例,后文会详细阐述)。这里有几点需要注意
因为每个 Thread 内有自己的实例副本,且该副本只能由当前 Thread 使用。这是也是 ThreadLocal 命名的由来
既然每个 Thread 有自己的实例副本,且其它 Thread 不可访问,那就不存在多线程间共享的问题
总的来说,ThreadLocal 适用于每个线程需要自己独立的实例且该实例需要在多个方法中被使用,也即变量在线程间隔离而在方法或类间共享的场景。后文会通过实例详细阐述该观点。另外,该场景下,并非必须使用 ThreadLocal ,其它方式完全可以实现同样的效果,只是 ThreadLocal 使得实现更简洁。
Spring
1、BeanFactory 和 FactoryBean?~BeanFactory是IOC最基本的容器,负责生产和管理bean,它为其他具体的IOC容器提供了最基本的规范;
FactoryBean是一个接口,当在IOC容器中的Bean实现了FactoryBean后,通过getBean(String BeanName)获取到的Bean对象并不是FactoryBean的实现类对象,而是这个实现类中的getObject()方法返回的对象;
2、Spring IOC 的理解,其初始化过程?~IoC文英全称Inversion of Control,即控制反转,我么可以这么理解IoC容器:
“把某些业务对象的的控制权交给一个平台或者框架来同一管理,这个同一管理的平台可以称为IoC容器。”
1-Resource定位(Bean的定义文件定位)
2-将Resource定位好的资源载入到BeanDefinition
3-将BeanDefiniton注册到容器中
3、BeanFactory 和 ApplicationContext?~BeanFactory 是 Spring 的“心脏”。它就是 Spring IoC 容器的真面目。Spring 使用 BeanFactory 来实例化、配置和管理 Bean。
如果说BeanFactory是Spring的心脏,那么ApplicationContext就是完整的躯体了,ApplicationContext由BeanFactory派生而来,提供了更多面向实际应用的功能。在BeanFactory中,很多功能需要以编程的方式实现,而在ApplicationContext中则可以通过配置实现。
4、Spring Bean 的生命周期,如何被管理的?~1. 实例化一个Bean,也就是我们通常说的new
2. 按照Spring上下文对实例化的Bean进行配置,也就是IOC注入
3. 如果这个Bean实现了BeanNameAware接口,会调用它实现的setBeanName(String beanId)方法,此处传递的是Spring配置文件中Bean的ID
4. 如果这个Bean实现了BeanFactoryAware接口,会调用它实现的setBeanFactory(),传递的是Spring工厂本身(可以用这个方法获取到其他Bean)
5. 如果这个Bean实现了ApplicationContextAware接口,会调用setApplicationContext(ApplicationContext)方法,传入Spring上下文,该方式同样可以实现步骤4,但比4更好,以为ApplicationContext是BeanFactory的子接口,有更多的实现方法
6. 如果这个Bean关联了BeanPostProcessor接口,将会调用postProcessBeforeInitialization(Object obj, String s)方法,BeanPostProcessor经常被用作是Bean内容的更改,并且由于这个是在Bean初始化结束时调用After方法,也可用于内存或缓存技术
7. 如果这个Bean在Spring配置文件中配置了init-method属性会自动调用其配置的初始化方法
8. 如果这个Bean关联了BeanPostProcessor接口,将会调用postAfterInitialization(Object obj, String s)方法
注意:以上工作完成以后就可以用这个Bean了,那这个Bean是一个single的,所以一般情况下我们调用同一个ID的Bean会是在内容地址相同的实例
9. 当Bean不再需要时,会经过清理阶段,如果Bean实现了DisposableBean接口,会调用其实现的destroy方法
10. 最后,如果这个Bean的Spring配置中配置了destroy-method属性,会自动调用其配置的销毁方法
5、Spring Bean 的加载过程是怎样的?~1. 加载XML文件,封装成Resource对象
2. 调用Reader对象方法读取XML文件内容,并将相关属性放到BeanDefinition实例
3. 将BeanDefinition对象放到BeanFactory对象
6、如果要你实现Spring AOP,请问怎么实现?7、如果要你实现Spring IOC,你会注意哪些问题?8、Spring 是如何管理事务的,事务管理机制?~Spring事务管理高层抽象主要包括3个接口,Spring的事务主要是由他们共同完成的:
PlatformTransactionManager:事务管理器—主要用于平台相关事务的管理
TransactionDefinition: 事务定义信息(隔离、传播、超时、只读)—通过配置如何进行事务管理。
TransactionStatus:事务具体运行状态—事务管理过程中,每个时间点事务的状态信息。
9、Spring 的不同事务传播行为有哪些,干什么用的?~1、PROPAGATION_REQUIRED:如果当前没有事务,就创建一个新事务,如果当前存在事务,就加入该事务,该设置是最常用的设置。
2、PROPAGATION_SUPPORTS:支持当前事务,如果当前存在事务,就加入该事务,如果当前不存在事务,就以非事务执行。‘
3、PROPAGATION_MANDATORY:支持当前事务,如果当前存在事务,就加入该事务,如果当前不存在事务,就抛出异常。
4、PROPAGATION_REQUIRES_NEW:创建新事务,无论当前存不存在事务,都创建新事务。
5、PROPAGATION_NOT_SUPPORTED:以非事务方式执行操作,如果当前存在事务,就把当前事务挂起。
6、PROPAGATION_NEVER:以非事务方式执行,如果当前存在事务,则抛出异常。
7、PROPAGATION_NESTED:如果当前存在事务,则在嵌套事务内执行。如果当前没有事务,则执行与PROPAGATION_REQUIRED类似的操作。
10、Spring 中用到了那些设计模式?~1-简单工厂
2-工厂方法
3-单例模式
4-适配器
5-包装器
6-代理
7-观察者
8-策略
9-模板方法
分布式相关1、Dubbo的底层实现原理和机制~1. client一个线程调用远程接口,生成一个唯一的ID(比如一段随机字符串,UUID等),Dubbo是使用AtomicLong从0开始累计数字的
2. 将打包的方法调用信息(如调用的接口名称,方法名称,参数值列表等),和处理结果的回调对象callback,全部封装在一起,组成一个对象object
3. 向专门存放调用信息的全局ConcurrentHashMap里面put(ID, object)
4. 将ID和打包的方法调用信息封装成一对象connRequest,使用IoSession.write(connRequest)异步发送出去
5. 当前线程再使用callback的get()方法试图获取远程返回的结果,在get()内部,则使用synchronized获取回调对象callback的锁, 再先检测是否已经获取到结果,如果没有,然后调用callback的wait()方法,释放callback上的锁,让当前线程处于等待状态。
6. 服务端接收到请求并处理后,将结果(此结果中包含了前面的ID,即回传)发送给客户端,客户端socket连接上专门监听消息的线程收到消息,分析结果,取到ID,再从前面的ConcurrentHashMap里面get(ID),从而找到callback,将方法调用结果设置到callback对象里。
7. 监听线程接着使用synchronized获取回调对象callback的锁(因为前面调用过wait(),那个线程已释放callback的锁了),再notifyAll(),唤醒前面处于等待状态的线程继续执行(callback的get()方法继续执行就能拿到调用结果了),至此,整个过程结束。
2、描述一个服务从发布到被消费的详细过程3、分布式系统怎么做服务治理~单provider,多cusumer,服务的注册和订阅
4、接口的幂等性的概念~多次操作返回同一结果
5、消息中间件如何解决消息丢失问题~事物,持久化,取消自动ack
6、Dubbo的服务请求失败怎么处理~查看管控台
查看注解
查看扫描包
查看发布服务
查看加载配置文件
7、重连机制会不会造成错误~不当的重连有可能会造成雪崩
8、对分布式事务的理解~原子性,一致性,隔离性,持久性
9、如何实现负载均衡,有哪些算法可以实现?
10、Zookeeper的用途,选举的原理是什么?
11、数据的垂直拆分水平拆分。
12、zookeeper原理和适用场景
13、zookeeper watch机制
14、redis/zk节点宕机如何处理
15、分布式集群下如何做到唯一序列号
16、如何做一个分布式锁
缓存
1、Redis用过哪些数据数据,以及Redis底层怎么实现
2、Redis缓存穿透,缓存雪崩
3、如何使用Redis来实现分布式锁
4、Redis的并发竞争问题如何解决
5、Redis持久化的几种方式,优缺点是什么,怎么实现的
6、Redis的缓存失效策略
7、Redis集群,高可用,原理
8、Redis缓存分片
9、Redis的数据淘汰策略
JVM
1、详细jvm内存模型
2、讲讲什么情况下回出现内存溢出,内存泄漏?
3、说说Java线程栈
4、JVM 年轻代到年老代的晋升过程的判断条件是什么呢?
5、JVM 出现 fullGC 很频繁,怎么去线上排查问题?
6、类加载为什么要使用双亲委派模式,有没有什么场景是打破了这个模式?
7、类的实例化顺序
8、JVM垃圾回收机制,何时触发MinorGC等操作
9、JVM 中一次完整的 GC 流程(从 ygc 到 fgc)是怎样的
10、各种回收器,各自优缺点,重点CMS、G1
11、各种回收算法
12、OOM错误,stackoverflow错误,permgen space错误
~OOM-OutOfMemory-堆内存溢出
stackoverflow-栈内存溢出
permgen space-永久空间
网友评论