JVM 内存区域从概念模型上主要分为 堆、元空间、java 虚拟机栈、本地方法栈、程序计数器 五大模块,其中前两者属于线程共享,而后三者属于线程私有,如下图(以 HotSpot 虚拟机为例):
说明:元空间在 java 8 中引入,替换之前的方法区。
JVM 内存区域从概念模型上主要分为 堆、元空间、java 虚拟机栈、本地方法栈、程序计数器 五大模块,其中前两者属于线程共享,而后三者属于线程私有,如下图(以 HotSpot 虚拟机为例):
说明:元空间在 java 8 中引入,替换之前的方法区。
在面向对象程序设计中,只要内存允许我们通常都可以为一个对象创建任意多个实例,但是一些场景下这不一定是一件好的事情。考虑一个文件类,在被使用之前需要从磁盘加载一定量的数据,我们肯定不希望每次调用该对象都去执行数据加载的操作,不仅费时,而且同样的数据因为一个对象的实例化操作就要在内存中重复存储一份,显然是对内存的一种浪费。这个时候我们就希望对数据的加载操作只执行一次,后面所有的调用都是对这份数据的复用,而这也正式单例模式的应用场景。
如果可以任意的创建对象,那么当我们希望内存中仅保有一份实例,就必须让所有的程序开发人员维持一个约定,只实例化该对象一次,然而现实是对象是可以任意被实例化的,约定开发人员是不现实的。这个时候我们就需要从开发人员手中剥夺对目标对象实例化的权利,而由单例模式去控制对象的创建,并暴露给开发人员一个获取对象实例的入口。
Java 8th 可以看做是 java 版本更新迭代过程中变化最大的几个版本之一(与时俱进,方能不灭),但是经过这么多年的发展和迭代,java 的源码俨然已是一个庞然大物,要在这样庞大的体积上大动干戈必定不易。所以当第一次看到默认接口方法的时候,我第一感觉就是这是设计人员在填自己之前挖的坑。
从前几篇的讲解中我们知道 8th 在现有的接口上添加了许多方法,比如 List 的 sort(Comparator<? super E> c)
方法。如果按照 8th 之前接口的设计思路,当给一个接口添加方法声明的时候,实现该接口的类都必须为该新添加的方法添加相应的实现(或将自己设置为抽象类)。考虑兼容性这样是不可取的,所以说这是一个坑,而新的特性又要求不得不为接口添加一些新的方法,为了兼得鱼和熊掌,设计人员提出了默认接口方法的概念。
第一次接触到流式数据处理的时候,第一感觉是流式数据处理让集合操作变得简洁了许多,通常我们需要多行代码才能完成的操作,借助于流式数据处理可以在一行中实现。比如我们希望对一个包含整数的集合筛选出所有的偶数,并将其封装成为一个新的集合返回,那么在 8th 之前,我们需要通过如下代码实现:
1 | List<Integer> evens = new ArrayList<>(); |
NullPointException 可以说是所有 java 程序员都遇到过的一个异常,虽然 java 从设计之初就力图让程序员脱离指针的苦海,但是指针确实是实际存在的,而 java 设计者也只能是让指针在 java 语言中变得更加简单、易用,而不能完全的将其剔除,所以才有了我们日常所见到的关键字 null
。
空指针异常是一个运行时异常,对于这一类异常,如果没有明确的处理策略,那么最佳实践在于让程序早点挂掉,但是很多场景下不是开发人员没有具体的处理策略,而是根本没有意识到空指针异常的存在。当异常真的发生的时候,处理策略也很简单,在存在异常的地方添加一个 if 语句判定即可,但是这样的应对策略会让我们的程序出现越来越多的 null 判定。
在分布式系统中著有 CAP 理论,该理论由加州大学伯克利分校的 Eric Brewer 教授提出,阐述了在一个分布式系统中不可能同时满足一致性( C onsistency)、可用性( A vailability),以及分区容错性( P artition Tolerance)。
ConcurrentHashMap 是线程安全的 HashMap。此前,HashTable 一直被认为是线程安全的 HashMap,ConcurrentHashMap 相对于 HashTable 采用了 锁分段机制 ,即将原本对整个对象加锁的实现进行粒度细化。这也是源于 HashMap 基本的存储特性,因为许多读写请求都是被哈希到了互相独立的区域,这种情况下即使并发读写也不会相互影响,更不会有线程安全问题,而对于操作加全局锁的实现方式显然是浪费了这一天然的并发优势,我们需要加锁的位置是真正存在竞争的地方,而分段锁很好的利用了这一特点。