Java基础必知必会
1. Java为什么要使用迭代器?
一种设计模式(迭代器模式:一种行为型模式):迭代模式是访问集合类的通用方法,只要集合类实现了Iterator接口,就可以用迭代的方式来访问集合类内部的数据,Iterator访问方式把对不同集合类的访问逻辑抽象出来,使得不用暴露集合内部的结构而达到循环遍历集合的效果;
2. Java线程池是如何回收线程的?
一个线程getTask()返回null就会被回收,有两种情况:
- 未调用shutdown()即RUNNING状态下的全部任务执行完成:线程数大于核心线程数,线程超时阻塞,超时唤醒后CAS减少工作线程数,当工作线程数小于等于核心线程数就可以一直阻塞。
- 调用shutdown()后,该方法会向所有线程发出中断信号,所有被阻塞的线程都会被唤醒回收,
3. Java中的守护线程与用户线程的区别?
Java中无论线程还是线程池默认都是用户线程,idDaemon()方法判断是否是守护线程;
守护线程是为用户线程服务的,用户线程都执行完毕之后守护线程也随之结束运行,即使守护线程仍然有任务需要执行也会结束(如果子线程是守护线程,用户线程的主线程调用join方法时会等待子线程执行完毕);
可以通过setDaemon()方法(该方法必须在start之前执行)将线程设置为守护线程,如果是线程池需要将线程池所有线程设置为守护线程,守护线程创建的子线程都是守护线程;
守护线程的应用场景:垃圾回收、服务端的检测线程等一些非核心非主流的服务业务;
线程优先级越高越早被执行的概率也越大,默认优先级为5,线程的类型与优先级无关;
4. 为什么使用异常捕获的代码比较耗费性能?
单从 Java 语法上看不出来,但是从 JVM 实现的细节上来看就明白了。构造异常实例,需要生成该异常的栈轨迹。该操作会逐一访问当前线程的栈帧,记录各种调试信息,包括类名,方法名,触发异常的代码行数等等。
5. finally如何实现无论异常与否都能执行?
编译器在编译代码时会复制 finally 代码块放在 try-catch 代码块所有正常执行路径以及异常执行路径的出口处。
6. finally 中有 ruturn 语句,catch 中抛出的异常会被忽略,为什么?
catch 抛出的异常会被 finally 捕获,执行完 finally 后会重新抛出该异常。由于 finally 中有 return 语句,在重新抛出异常之前,代码就已经返回了。
7. 方法的异常表都包含哪些异常?
方法的异常表只声明这段代码会被捕获的异常,而且是非检查异常。如果 catch 中有自定义异常,那么异常表中也会包含自定义异常的条目。
8. 检查异常和非检查异常也就是其他书籍中说的编译期异常和运行时异常?
检查异常也会在运行过程中抛出。但是它会要求编译器检查代码有没有显式地处理该异常。非检查异常包括 Error 和 RuntimeException,这两个则不要求编译器显式处理。
9. java的引用类型
- ReferenceQueue引用队列:与某个引用类绑定,当引用死亡后,会进入这个队列
- HardReference强引用:任何以String str = new String()建立起来的引用都是强引用,在str指向另一个对象或者null之前,该String对象都不会被GC回收
- WeakReference弱引用:可通过其建立弱引用,当GC要求回收对象时,它不会阻止对象被回收,即:如果该对象仅存在弱引用,那么该对象会被回收
- SoftReference软引用:与弱引用类似,不同的是回收过程会被延迟,必须等到JVM的heap内存不足接近产生OutOfMemory时才会被回收
- PhantomReference虚引用:大多数时间无法取到其引用的对象,当这个对象死亡时会进入ReferenceQueue队列;虚引用非常弱,以至于它自己都找不到自己引用的内容
10. QPS,TPS,并发数,吞吐量
- QPS
Queries Per Second是每秒查询率 ,是一台服务器每秒能够相应的查询次数,是对一个特定的查询服务器在规定时间内所处理流量多少的衡量标准, 即每秒的响应请求数,也即是最大吞吐能力。 - TPS
Transactions Per Second也就是事务数/秒。一个事务是指一个客户机向服务器发送请求然后服务器做出反应的过程。客户机在发送请求时开始计时,收到服务器响应后结束计时,以此来计算使用的时间和完成的事务个数 - 并发数(并发度):指系统同时能处理的请求数量,同样反应了系统的负载能力。
- 吞吐量是指系统在单位时间内处理请求的数量,TPS、QPS都是吞吐量的常用量化指标。

浙公网安备 33010602011771号