1.new 对象和 声明对象区别
People p = new People (); 和 Poeple p;
前者是在堆上面创建了内存空间而且p指向了该空间。后者只是一个空指针,没有指向任何存储地址。
如果 将上述的p = man;那么前者和后者就都一样了,只是第一种方式声明的对象空间被丢弃,在垃圾回收的时候被释放回收。
2.static修饰类
对于内部类,为了将其对于其他类可见,而且不用先声明父类,再调用这个子类。那么这样就可以将这个内部类声明称static。
3.private、protected 和public都可以声明构造方法,对于单例模式一般构造方法为private,而newinstance为public static类型,防止使用者直接使用构造方法构造对象。
4.Java目前有9对应jdk是1.9,那么jdk1.5,1.6,1.7,1.8,对应Java分别是5,6,7,8。
5.Java几种垃圾回收器
- Serial Garbage Collector
- Parallel Garbage Collector
- CMS Garbage Collector
- G1 Garbage Collector
这四种垃圾收集器每一种都有自己的优点与不足。最重要的是,我们开发人员可以选择Java虚拟机使用的垃圾收集器的类型。我们可以通过传从参数的形式,来选择它们。每一种垃圾收集器都有非常大的特点,都可以提供完全不同的性能。必须严谨而准确地理解这集中垃圾收集器,然后基于应用的使用情况正确选择。
1. Serial Garbage Collector
Serial Garbage Collector通过暂停所有应用的线程来工作。它是为单线程工作环境而设计的。它中使用一个线程来进行垃圾回收。这种暂停应用线程来进行垃圾回收的方式可能不太适应服务器环境。它最适合简单的命令行程序。
通过 -XX:+UseSerialGC
参数来选用Serial Garbage Collector。
2. Parallel Garbage Collector
Parallel Garbage Collector也被称为吞吐量收集器(throughput collector)。它是Java虚拟机的默认垃圾收集器。与Serial Garbage Collector不同,Parallel Garbage Collector使用多个线程进行垃圾回收。与Serial Garbage Collector相似的地方时,它也是暂停所有的应用线程来进行垃圾回收。
3. CMS Garbage Collector
Concurrent Mark Sweep (CMS) Garbage Collector使用多个线程来扫描堆内存来标记需要回收的实例,然后再清除被标记的实例。CMS Garbage Collector只有在如下两种情景才会暂停所有的应用线程:
- 当标记永久代内存空间中的对象时;
- 当进行垃圾回收时,堆内存同步发生了一些变化。
相比Parallel Garbage Collector,CMS Garbage Collector使用更多的CPU资源来确保应用有一个更好的吞吐量。如果分配更多的CPU资源可以获得更好的性能,那么CMS Garbage Collector是一个更好的选择,相比Parallel Garbage Collector。
通过 XX:+USeParNewGC
参数来选用CMS Garbage Collector。
4. G1 Garbage Collector
G1 Garbage Collector用于大的堆内存区域。它将堆内存分割成多个独立区域(Region),然后并发地对它们进行垃圾回收。在释放内存后,G1还可以压缩空闲的堆内存。但是,CMS Garbage Collector是通过“Stop The World (STW)”来进行内存压缩的。G1优先收集可回收更多内存的区域。
通过 –XX:+UseG1GC
参数来选用G1 Garbage Collector。
Java 8 的改进
在用G1 Garbage Collector时,可以开启 -XX:+UseStringDeduplication
参数。它通过将重复的字符串移动到同一个 char
数组中来优化堆内存的使用。该选项在Java
8u20时引用进来。
上面给出了四种垃圾收集器的介绍,至于选用哪个垃圾收集器,这个要根据应用场景、可用的硬件资源以及吞吐量的要求来确定。
Java虚拟机中的垃圾回收选项
下面是与Java收集器相关的Java虚拟机选项。
垃圾收集器选择
Option | Description |
---|---|
-XX:+UseSerialGC | Serial Garbage Collector |
-XX:+UseParallelGC | Parallel Garbage Collector |
-XX:+UseConcMarkSweepGC | CMS Garbage Collector |
-XX:ParallelCMSThreads= | CMS Collector – 使用的线程数 |
-XX:+UseG1GC | G1 Gargbage Collector |
垃圾回收优化选项
Option | Description |
---|---|
-Xms | 堆内存初始化尺寸 |
-Xmx | 堆内存最大尺寸 |
-Xmn | 新生代(Young Generation)的尺寸 |
-XX:PermSize | 永久代(Permanent Generation)初始化尺寸 |
-XX:MaxPermSize | 永久代(Permanent Generation)最大尺寸 |
Java虚拟机垃圾回收选项的使用示例
java -Xmx12m -Xms3m -Xmn1m -XX:PermSize=20m -XX:MaxPermSize=20m -XX:+UseSerialGC -jar java-application.jar
对于内存的划分和管理,一般是操作系统(不管是什么编译器编译的程序)。但是对于Java虚拟机需要管理自己的内存堆,那么必然对内存堆有自己的分区,而且不同版本 的jvm对内存的划分不一样。
6.Java 对象数组
Object[]
objArr =
new
Object[
1000
];
String[]
strarry = new String[10];
String[] strarry = {"","","","","",""};
7.java
中四大引用 -- 强引用,软引用,弱引用和虚引用。
强引用:无论内存是否足够,不会回收,即使爆出来oom也不会回收。
软引用:内存不足时,回收该引用关联的对象。
弱引用:垃圾回收时,无论内存是否足够,都会回收。
虚引用:任何时候都可能被垃圾回收器回收。
transient
transient是类型修饰符,只能用来修饰字段。在对象序列化的过程中,标记为transient的变量不会被序列化。
示例:
transient int a; // 不会被持久化
int b; // 持久化
}
当类Test的实例对象被序列化(比如将Test类的实例对象 t 写入硬盘的文本文件t.txt中),变量 a 的内容不会被保存,变量 b 的内容则会被保存。
参考:
把一个对象的表示转化为字节流的过程称为串行化(也称为序列化,serialization),从字节流中把对象重建出来称为反串行化(也称为为反序列化,deserialization)。transient 为不应被串行化的数据提供了一个语言级的标记数据方法。
volatile
volatile也是变量修饰符,只能用来修饰变量。volatile修饰的成员变量在每次被线程访问时,都强迫从共享内存中重读该成员变量的值。而且,当成员变量发生变化时,强迫线程将变化值回写到共享内存。这样在任何时刻,两个不同的线程总是看到某个成员变量的同一个值。
在此解释一下Java的内存机制:
Java使用一个主内存来保存变量当前值,而每个线程则有其独立的工作内存。线程访问变量的时候会将变量的值拷贝到自己的工作内存中,这样,当线程对自己工作内存中的变量进行操作之后,就造成了工作内存中的变量拷贝的值与主内存中的变量值不同。
9.Java 并发与并发容器 -- ConcurrentCopyOnWriteArrayList与Copy-On-Write策略
Copy-On-Write简称COW,是一种用于程序设计中的优化策略。其基本思路是,从一开始大家都在共享同一个内容,当某个人想要修改这个内容的时候,才会真正把内容Copy出去形成一个新的内容然后再改,这是一种延时懒惰策略。从JDK1.5开始Java并发包里提供了两个使用CopyOnWrite机制实现的并发容器,它们是CopyOnWriteArrayList和CopyOnWriteArraySet。CopyOnWrite容器非常有用,可以在非常多的并发场景中使用到。
CopyOnWrite容器即写时复制的容器。通俗的理解是当我们往一个容器添加元素的时候,不直接往当前容器添加,而是先将当前容器进行Copy,复制出一个新的容器,然后新的容器里添加元素,添加完元素之后,再将原容器的引用指向新的容器。这样做的好处是我们可以对CopyOnWrite容器进行并发的读,而不需要加锁,因为当前容器不会添加任何元素。所以CopyOnWrite容器也是一种读写分离的思想,读和写不同的容器。
CopyOnWrite容器只能保证数据的最终一致性,不能保证数据的实时一致性。所以如果你希望写入的的数据,马上能读到,请不要使用CopyOnWrite容器。
ConcurrentLinkedQueue
在并发编程中,有时候需要使用线程安全的队列或列表。通常实现线程安全有两种方式,一种是使用阻塞算法,一种是使用非阻塞算法。非阻塞算法实现基础为循环CAS(Compare and Swipe 比较和交换)。
ConcurrentLinkedQueue技术上的实现与CopyOnWriteArrayList与Copy类似,但是容器只有部分内容而不是整个容器可以被复制和修改。ConcurrentLinkedQueue有head节点和tail节点组成,每个节点由节点元素(item)和指向下一个结点(next)的引用组成。节点之间通过next关联起来,形成一张链表结构的队列。
ConcurrentHashMap与锁分段技术
ConcurrentHashMap是线程安全且高效的HashMap。多线程环境下,使用非线程安全的HashMap会导致死循环,而如文章中建议的那样,HashTable这种过时容器效率低下(使用synchronized来保证线程安全)。ConcurrentHashMap使用锁分段技术,大大提高了并发使用的效率。
锁分段技术: 假设容器有多把锁,每一把锁用于锁容器其中一部分数据,当多线程访问容器不同数据段数据时,线程间就不存在锁竞争,从而提高并发访问效率。
方法重写:它是指子类和父类的关系,子类重写了父类的方法,但方法名、参数类型、参数个数必须相同!