乐趣区

关于java:面试题

一 JVM 内存区域

1)办法区:寄存要加载类的信息(类名,修饰符),动态变量,构造函数,final 定义的常数。
运行时常量池在这里,用于生成和贮存常量的援用。
在 host 中对应长久代。执行 GC 的状况少
2)堆
GC 最频繁的,线程共享,在虚拟机启动时创立。堆里寄存实例,数组,new 对象
3)虚拟机栈
每个线程对应一个虚拟机栈,它是线程公有,生命周期和线程一样,每个办法被执行时产生一个栈帧,栈帧用于存储局部变量表、动静链接、操作数和办法进口等信息,当办法被调用时,栈帧入栈,当办法调用完结时,栈帧出栈。

4)本地办法栈
本地办法栈用于反对 native 办法的执行,存储了每个 native 办法的执行状态。
虚拟机执行 Java 办法。
5)程序计数器
划分在 CPU 上
作用是:JVM 在解释字节码(.class)文件时,存储以后线程执行的字节码行号
每个程序计数器只能记录一个线程的行号,因而它是线程公有的。
如果程序以后正在执行的是一个 java 办法,则程序计数器记录的是正在执行的虚拟机字节码指令地址,如果执行的是 native 办法,则计数器的值为空,此内存区是惟一不会抛出 OutOfMemoryError 的区域。

二 GC 机制
本地办法栈,程序计数器,虚拟机栈 不须要进行垃圾回收,因为生命周期是跟线程同步的随着线程的销毁,内存会主动开释。
办法区和堆区须要垃圾回收。

查找内存的办法:

 援用计数法:援用一次就加 1,有个问题两个对象相互援用,然而都曾经没用了
 可达性剖析:从一个 GC roots 的根节点登程,向下搜寻,找到的标记,没找到的就是垃圾

 强援用:new 进去的都是强援用
 软援用:只有 JVM 内存不足就被回收
 弱援用:只有 GC,就立马回收
 虚援用:作用就是做一些跟踪记录

什么样的类须要被回收:
1 该类的所有实例都曾经被回收
2 加载该类的 ClassLoad 曾经被回收
3 该类对应的反射 Java.lang.Class 对象没有被任何中央援用

垃圾革除的中央次要针对堆

总共 10,伊甸园区 8,s0 1,s1 1 又叫幸存区
总共 3G,老年代 2G,年老代 1G
年老代失常状况下创建对象,默认在伊甸园区里,伊甸园满了就要回收,用可达性算法去回收。
如果有援用是不能被回收的,那就利用复制算法,挪到 S0 外面去,同时标记一下,达到空间
当 S0 也收满了,S1 也会进行回收
S1 对伊甸园进行判断,并进行年纪判断,活下来的记录为 1。
S2 回收 S0 的,用可达性剖析,这个年纪就为 2.
如果经验了 15 次还没有死掉,就放入老年代

老年代如果满了,产生一种负 GC,还是用可达性剖析进行
年老代 GC 的时候工夫会短
老年代工夫负 GC 工夫长,须要尽量减少负 GC,要回收整个区域。
大部分时候应用标记整顿法。


它有着优于其余收集器的中央:简略而高效,对于限定单个 CPU 的环境来说,Serial 收集器因为没有线程交互的开销,分心做垃圾收集天然能够取得最高的单线程收集效率。


Parallel Scavenge 的特别之处就在于它关注的是吞吐量,也就是运行代码工夫与(运行代码工夫 + 垃圾收集器工夫)的比值,比方运行代码工夫为 99 分钟,垃圾收集器运行工夫为 1 分钟,那么吞吐量就是 99%,谋求高吞吐量能够最大水平的利用 CPU 资源实现运算的工作,这就比拟适宜关注后盾运算,而与用户交互较少的场景。

后面两个都会产生 stw,进展

Cms 四个步骤:初始标记:与对象由关系的,会产生 stw,
并发标记不会产生暂停,会有错乱景象,会有漏标景象,在从新标记的阶段补上,在并发清理开始革除


双亲委派机制

类加载器的类别

BootstrapClassLoader(启动类加载器)

c++编写,加载 java 外围库 java.*, 结构 ExtClassLoaderAppClassLoader。因为疏导类加载器波及到虚拟机本地实现细节,开发者无奈间接获取到启动类加载器的援用,所以不容许间接通过援用进行操作

ExtClassLoader(规范扩大类加载器)

java编写,加载扩大库,如 classpath 中的 jrejavax.* 或者
java.ext.dir 指定地位中的类,开发者能够间接应用规范扩大类加载器。

AppClassLoader(零碎类加载器)

java编写,加载程序所在的目录,如 user.dir 所在的地位的class

CustomClassLoader(用户自定义类加载器)

java编写, 用户自定义的类加载器, 可加载指定门路的 class 文件

Mtbatis 缓存 默认一级 sqlsessison 级别
一级:同一个 sqlSession 对于一个 SQL 语句,执行后就存在缓存中,下次就从缓存里取,test 操作的时候,第一次上面是会有 SQL 语句的,第二次是没有的。
生效状况:1 同一个 Sqlseeion 语句要求是,所以不同 sqlSession 必定生效。
2 两次查问期间执行了任何一次增删改操作
3 革除了缓存也就是应用了 sqlSession.clearCache 办法
二级 须要手动开启 映射文件级别
1 在 xml 中 value 改成 true,setting name cacheEnabled
2 在须要应用的映射文件加上 cache 配置
3 pojo 类须要实现序列化接口
二级缓存的回收策略:
1 LRU 最近最小应用

FIFO:先进先出
SOFT:移除软援用的对象
WEAK:移除弱援用的对象

测试二级缓存,把一级缓存敞开了

整合第三方缓存:实现 Cache 接口

             EhCache 缓存框架
             导入 ehcache 包,以及整合包,日志包
             
             

mybatis 一对多,增加一个部门
能够依据 name,name 一样的话,应用自增的主键

userGeneratedKeys=true keyProperty=“把自增的主键放在哪,赋值给传递过去的哪一个属性?”传过来的是一个 emp 对象
当传两个或者多个参数值的时候,mybatis 会默认将这些参数放在 map 汇合中
两种形式:
1)键为:0,1,2,3,4,…. 以参数为值
2)键为 param1,param2,param3,param4 以参数为值
1)Dept 设置的是别名,把 did 和 dname 赋值给 dept 这个对象
关联对应的话,就是用 id coium 主键映射 对应的关系
多个参数就是 map 汇合


还有 where in
批量批改吧默认批改很多条变成容许

多线程
首先线程贮存在栈里
对于过程:特点:1 独立性:有公有的地址空间。被拜访须要过程本身的容许
2 动态性:有生命周期,和不同的状态,一个零碎中流动的指令
3 并发性:多个过程在单个处理器上并发进行,多个过程之间不会相互影响
线程的进行是随机

线程的状态

1 新建状态 线程对象创立实现
2 就绪状态,线程调用对象执行了 start()办法
3 执行状态,线程被 CUP 调用的时候
4 阻塞状态,运行的线程因为某些起因放弃了对 cpu 的使用权
分为三类:1 期待阻塞:线程执行的过程中应用了 wait 办法,是本线程进入阻塞状态
2 同步阻塞:线程执行的时候获取同步锁失败了,锁被其余线程占用了。
3 其余阻塞,比方线程执行了 sleep()办法引起的阻塞
5 死亡状态,执行完结或者因为异样退出的 run()办法,完结了线程生命周期
wait 办法和 sleep()办法的差异
应用 wait 办法会开释锁,而 sleep 办法不会去开释锁
wait 用于线程交互,sleep 用于线程暂停
14、什么是 Callable 和 Future?

Callable 接口相似于 Runnable,但 Runnable 不会返回后果,并且无奈抛出返回后果的异样,而 Callable 被线程执行后,能够返回值,这个返回值能够被 Future 拿到,也就是说,Future 能够拿到异步执行工作的返回值。
能够认为是带有回调的 Runnable。
Future 接口示意异步工作,是还没有实现的工作给出的将来后果。所以说 Callable 用于产生后果,Future 用于获取后果。

线程互斥
有若干个线程都要应用某一共享资源时,任何时刻最多只容许一个线程去应用,其它要应用该资源的线程必须期待,直到占用资源者开释该资源。线程互斥能够看成是一种非凡的线程同步。

为什么调用 start 办法是会执行 run()办法,而不能间接执行 run()办法?
因为 start 办法执行,代表创立新的线程,线程启动了,并且会执行 run 办法里的代码。
执行 run 办法并不会去创立线程,也不会去调用线程,只是把 run 办法当做一般办法进行。

不可变对象:String,根本类的包装类 天生线程平安

线程中的调度算法:抢占式调度,优先级高的先占用,
一个是分时调度

为什么应用 Executor 康佳比应用利用线程要好?
1)复用曾经存在的线程缩小对线程对象的创立和销毁
2)无效管制最大并发线程,进步资源利用率
3)框架中有定时,定期,扩大的性能

如何进行一个正在运行的线程?
应用 Thread 里的 interrupt 办法,是一个运行中的线程不会去中断它,而是是一个被阻塞的线程抛出异样,提前结束阻塞状态,退出。

notify()和 notifyall 办法,用来唤醒应用了 wait()办法的线程,后面只能唤醒一个。

所谓后盾 (daemon) 线程,是指在程序运行的时候在后盾提供一种通用服务的线程
JVM 的垃圾回收线程就是 Daemon 线程,Finalizer 也是守护线程。

可反复锁:线程能够进入人一个它曾经领有的锁同步的代码块。
synchronized、ReentrantLock 都是可重入的锁,可重入锁相对来说简化了并发编程的开发。

乐观锁和乐观锁
乐观锁:每次获取数据都认为,他人会来取,所以就给数据上锁,他人想拿这个数据就会梗塞,直到它拿到锁。数据库里表锁,行锁就是这种但凡,操作前先上锁。java 里的 Synchronized
乐观锁:每次拿数据的时候,都感觉他人不会批改,只有更新的时候会去判断一下这个期间有没有更新过数据。
实现形式:1 版本标识来确定一下读到的数据是否与提交的数据统一。
2 当多个线程尝试应用 CAS 同时更新同一个变量时,只有其中一个线程能更新变量的值,而其它线程都失败,失败的线程并不会被挂起,而是被告知这次竞争中失败,并能够再次尝试。CAS 操作中蕴含三个操作数 —— 须要读写的内存地位(V)、进行比拟的预期原值(A)和拟写入的新值(B)。如果内存地位 V 的值与预期原值 A 相匹配,那么处理器会主动将该地位值更新为新值 B。否则处理器不做任何操作。
CAS 毛病:
1、ABA 问题:
比如说一个线程 one 从内存地位 V 中取出 A,这时候另一个线程 two 也从内存中取出 A,并且 two 进行了一些操作变成了 B,而后 two 又将 V 地位的数据变成 A,这时候线程 one 进行 CAS 操作发现内存中依然是 A,而后 one 操作胜利。只管线程 one 的 CAS 操作胜利,但可能存在潜藏的问题。从 Java1.5 开始 JDK 的 atomic 包里提供了一个类 AtomicStampedReference 来解决 ABA 问题。
2、循环工夫长开销大:
对于资源竞争重大(线程抵触重大)的状况,CAS 自旋的概率会比拟大,从而节约更多的 CPU 资源,效率低于 synchronized。
3、只能保障一个共享变量的原子操作:
当对一个共享变量执行操作时,咱们能够应用循环 CAS 的形式来保障原子操作,然而对多个共享变量操作时,循环 CAS 就无奈保障操作的原子性,这个时候就能够用锁。

SynchronizedMap 和 ConcurrentHashMap 的区别?
Synchronized 是锁住一个表,只有一个锁
ConcurrentHashMap 是简化 hash 表分为 16 个桶,一个桶一个锁,一次锁住一个桶。

volatile 的应用场景?
volatile 保障内存可见性和禁止指令重排
volatile 用于多线程下的单次操作(单次读或者写)

wait,notify,notifyAll 不在 thread 类里?
因为 Java 提供的锁不是线程级,是对象级的。

ThreadLocal 是 Java 里一种非凡的变量。每个线程都有一个 ThreadLocal 就是每个线程都领有了本人独立的一个变量,竞争条件被彻底消除了。它是为创立代价昂扬的对象获取线程平安的好办法,比方你能够用 ThreadLocal 让 SimpleDateFormat 变成线程平安的,因为那个类创立代价昂扬且每次调用都须要创立不同的实例所以不值得在部分范畴应用它,如果为每个线程提供一个本人独有的变量拷贝,将大大提高效率。首先,通过复用缩小了代价昂扬的对象的创立个数。其次,你在没有应用高代价的同步或者不变性的状况下取得了线程平安。

interrupt 就中断线程,处于一个中断状态
interrupted 查问线程的中断状态,并把这个状态革除了

怎么查看线程是否领有锁?holdslock()的办法

Tread 中 yield 办法:使线程从运行状态变为就绪状态

线程池中 submit()和 execute 办法区别?
execute 办法返回的是 void,submit 返回的是 future 对象

能够间接调用 run 办法然而就是和一般办法一样,要执行线程中的办法必须要 start 办法

如何确保 main()办法所在的线程是 Java 程序最初完结的线程?
应用 Thread 类里的 join()办法确保所有程序创立的线程在 main()办法退出前完结。
join()办法就是让 CPU 先执行这个办法

线程之间的通信:wait,notify,notifyAll。

保障线程平安方法:应用并发锁,应用 volatile 关键字,应用线程安全类

同步块比同步办法好,限定的范畴小,不会锁住整个对象

创立守护线程:Thread 类的 setDaemon(true),用之前要 start 办法

java.util.Timer 是一个工具类,能够用于安顿一个线程在将来的某个特定工夫执行。Timer 类能够用安顿一次性工作或者周期工作。
java.util.TimerTask 是一个实现了 Runnable 接口的抽象类,咱们须要去继承这个类来创立咱们本人的定时工作并应用 Timer 去安顿它的执行。

什么是反射:能够在运行时获取一个类的所有信息,能够获取到任何定义的信息(包含成员变量,成员办法,结构器等),并且可操纵类的字段,办法,结构器等局部。
获取残缺类名:

退出移动版