Java基础

1.Finally执行流程

总结:finally在try和exception之后执行,尽量不要在finally里面进行return操作,finally 总是执行,除非程序或者线程被中断

2.强引用/软引用/弱引用/幻象引用(虚引用)

总结:

强引用:最常用

软引用:内存空间不足才会被回收,可用来实现很多内存敏感点的缓存场景

弱引用:比软引用的生命周期更短,不管内存是否有空现,都会立刻回收它

幻象引用(虚引用):提供了一种确保对象被finalize以后,做某些事情的机制,有人利用幻象引用监控对象的创建和销毁

3.自动拆箱和自动装箱

4.LruCache和DiskLruCache

5.Volatile关键字

(1)保证此变量对所有线程的可见性。当一个线程修改了这个变量的值,volatile保证了新值能立即同步到主内存以及每次使用前从主内存刷新(跳过CPU cache这一步)

(2)禁止指令重排序(CPU采用了允许将多条指令不按程序规定的顺序分开发送给各相应电路单元处理)优化

6.transient关键字

总结:

(1)使用方法:

​ 类中的敏感数据变量标记为transient,不做序列化

(2)使用小结:

①一旦变量被transient修饰,变量将不再是对象持久化的一部分,该变量内容在序列化后无法获得访问。

②transient关键字只能修饰变量,而不能修饰方法和类。注意,本地变量是不能被transient关键字修饰的。变量如果是用户自定义类变量,则该类需要实现Serializable接口。

③被transient关键字修饰的变量不再能被序列化,一个静态变量不管是否被transient修饰,均不能被序列化。

transient:被标记为transient的变量不会被序列化

(3)被transient关键字修饰的变量真的不能被序列化吗?

若实现的是Serializable接口,则所有的序列化将会自动进行,若实现的是Externalizable接口,则没有任何东西可以自动序列化,需要在writeExternal方法中进行手工指定所要序列化的变量,这与是否被transient修饰无关

7.ReentrantReadWriteLock

读锁(ReentrantReadWriteLock.WriteLock):共享锁,前提条件:

(1)没有其他线程的写锁

(2)没有写请求或者有写请求,但调用线程和持有锁线程是同一个

写锁(ReentrantReadWriteLock.ReadLock):排他锁

(1)没有其他线程的读锁,没有其他线程的写锁

读-写互斥、写-读互斥、写写互斥、读读共享

三个重要特性:

(1)公平选择性:支持非公平的(默认)和公平的锁获取方式,吞吐量还是非公平优于公平

(2)重进入:读锁和写锁都支持线程重进入

(3)锁降级:遵循获取写锁、获取读锁再释放写锁的次序,写锁能够降级成为读锁

公平锁

8.ReentrantLock

总结:

ReentrantLock是基于AQS实现的,AQS的基础又是CAS

9.synchronized,wait,notify

10.公平锁和非公平锁

11.Unsafe和CAS

12.ThreadLocal

13.String/StringBuffer/StringBuilder的区别

总结:

StringBuffer线程安全,通过把各种修改数据的方法都加上synchronized关键字实现的。

StringBuilder非线程安全

String内部不可修改

StringBuffer和StringBuilder底层都是利用可修改的数组,二者都继承了AbstractStringBuidler。构建时初始字符串长度为16,如果确定拼接会发生非常多次而且大概可预计,那么可以指定合适的大小,避免多次扩容的开销。

14.hashCode和equals

总结:

hashCode()的作用是获取哈希码,实际上是返回一个int整数

equals()的作用是判断两个对象是否相等,如果对象重写了equals方法,比较两个对象的内容是否相等;如果没有重写,比较两个对象的地址是否相同,等价于’’==’’

如果类使用在散列表(HashSet, HashTable, HashMap)的集合对象中,要判断两个对象是否相同,除了要覆盖equals之外,也要覆盖hashCode,否则equals()无效

复写hashCode的诀窍

1
2
3
4
5
6
@Override
public int hashCode() {
int result = 17;
result = 31 * result + name.hashCode();
return result;
}

15.sleep和wait的区别

(1)在等待时wait会释放锁,而sleep一直持有锁。wait通常被用于线程间交互,sleep通常用于暂停执行。

(2)sleep是Thread类的静态方法,wait是object方法

(3)wait/notify/notifyAll只能在同步c控制方法或者同步控制块里使用,而sleep可以在任何地方使用

(4)sleep必须捕获,而wait/notify/notifyAll不需要捕获异常

16.CyclicBarriar和CountdownLatch

CountdownLatch:一个线程(或者多个),等待另外N个线程完成某个事情之后才执行。内部使用AQS(AbstractQueuedSynchronizer)和CAS实现,AQS其中一个作用就是维护线程状态和获取释放锁。

CyclicBarriar:N个线程相互等待,任何一个线程完成之前,所有的线程都必须等待。基于ReentrantLock重入锁实现

17.IO/NIO/AIO

18.一个hello,world程序创建了几个线程

jdk1.8:5个线程

main:主线程

Reference Handler:处理引用对象本身的垃圾回收

Finalizer:处理用户的Finalizer方法

Signal Dispatcher:外部jvm命令的转发器

Attach Listener:jvm提供一种jvm进程间通信的能力,能让一个进程传命令给另外一个进程

19.注解

注解库:javapoet和asm