这一篇文章,主要是对Java基础的回顾,对一些容易遗忘的知识点进行再次巩固。针对之前篇章中出现的未能及时阐述清楚的概念,再次进行阐述。例如基础篇三中:锁的概念,将在本文中进一步阐述;
1、反射为什么会说是效率低?
在获取反射类的过程中,getxxxMethod()和invoke() 方法会对参数做封装和解封操作; 调用checkMemberAccess()来检查类方法权限,需要检查方法可见性; getxxxMethod()传入的参数需要校验,不同参数类型; 各处的反射调用,在调用点上收集到的类型信息很乱,影响内联程序的判断,反射方法难以内联; 射涉及到动态加载的类型,JIT 无法优化。
2、怎样提高反射的效率?
项目启动的时候将反射所需要的相关配置及数据加载进内存中,在运行阶段都从缓存中取这些元数据进行反射操作。
前几篇文章,对反射进行了简单解读,没有考虑到很多深层次的问题,直接看到了结果,而没有思考为什么会出现这样的结果。这对于一个初级程序员升级来说,是非常致命,不去阅读源码,贪心求快,最终的结果就是基础不牢,耽误自己提升的机会。
3、锁?
自旋锁
是指当一个线程在获取锁的时候,如果此时锁已经被其它线程获取,那么该线程将循环等待,处于一种忙等待中,不断的判断锁是否已经成功获取,直到获取到锁才会退出循环。
公平锁
加锁前先查看是否有排队等待的线程,有的话优先处理排在前面的线程,先来先得。
非公平锁
线程加锁时直接尝试获取锁,获取不到就自动到队尾等待。
悲观锁
总是假设最坏的情况,每次去拿数据的时候都认为别人会修改,所以每次在拿数据的时候都会上锁,这样别人想拿这个数据就会阻塞直到它拿到锁(共享资源每次只给一个线程使用,其它线程阻塞,用完后再把资源转让给其它线程)。传统的关系型数据库里边就用到了很多这种锁机制,比如行锁,表锁等,读锁,写锁等,都是在做操作之前先上锁。Java中synchronized和ReentrantLock等独占锁就是悲观锁思想的实现。
乐观锁
总是假设最好的情况,每次去拿数据的时候都认为别人不会修改,所以不会上锁,但是在更新的时候会判断一下在此期间别人有没有去更新这个数据,可以使用版本号机制和CAS算法实现。乐观锁适用于多读的应用类型,这样可以提高吞吐量,像数据库提供的类似于write_condition机制,其实都是提供的乐观锁。在Java中java.util.concurrent.atomic包下面的原子变量类就是使用了乐观锁的一种实现方式CAS实现的。
可重入锁
广义上的可重入锁指的是可重复可递归调用的锁,简单解释就是在外层使用锁之后,在内层仍然可以使用(同一个对象使用同一把锁),这样的锁就叫做可重入锁, ReentrantLock和synchronized都是可重入锁。通俗一点说就是,你开了大门锁,现在开房间门锁;如果你不是同一把锁,那么房间门是打不开的。
不可重入锁
不可重入锁与可重入锁相反,是不可重复,不可递归调用的锁,一但重复或者递归调用就会发生死锁。
开发中怎样使用基本的工具,比如在new ArrayList()、new hashMap()最好考虑到初始化,扩容机制的问题,尽可能的减少扩容;String类型判断不为空(String的方法),list判断不为空(使用集合类工具Conllections ,不要使用==);正确使用equals方法,确定不为null的值放在前面,这样是避免空指针异常的抛出;包装类与基本类型的转换需注意范围。更多开发要则,请详细研究《阿里Java开发手册》--《码出真经》,有机会对强制执行的规定,进行进一步的解读,看看为什么要这样做。