Java相关知识点整理《一》

1、JVM内存模型。

1.1.程序计数器。

当前线程所执行的字节码的行号指示器。

1.2.Java虚拟机栈。

线程私有,生命周期与线程相同,描述的是Java方法执行的内存模型。

​​​​​​​1.3.本地方法栈。

虚拟机栈为虚拟机执行Java方法(也就是字节码)服务,而本地方法栈则是为虚拟机中使用到的Native方法服务。

1.4.Java堆。

Java堆是被所有线程共享的一块内存区域,在虚拟机启动的时候创建。

1.5.方法区。

与堆一样,各个线程共享的区域,用于存储已被虚拟机加载的类信息、常量、静态变量、即时编译器(运行时常量池)编译后的代码等数据。

2、类加载机制。

class文件由类装载器装载后,在JVM中形成一份描述class结构的元信息对象,通过元信息对象可以获知class的结构信息;如构造函数、属性和方法等。Java允许用户借由这个class相关的元信息对象间接调用class对象的功能。

虚拟机把描述类的数据从class文件加载到内存,并对数据进行校验、转化解析和初始化,最终形成可被虚拟机直接使用的Java类型,这就是类加载机制。

3、什么是Java垃圾回收机制(GC)。

在系统运行过程中,会产生一些无用的对象,这些对象占据着一定的内存,如果不对这些对象清理无用的内存,可能会导致内存耗尽,所以垃圾回收机制回收的是内存。同时GC回收的是堆区和方法区的内存。

4、垃圾回收算法整理。

4.1.引用​​​​​​​计数器算法。

是否有任一地方对对象进行了调用(对象是否已死)。

​​​​​​​4.2.可达性分析算法。

选择一个节点作为GC Roots,校验从GC Roots是否可达当前对象(对象是否已死)。

​​​​​​​​​​​​​​4.3.标记-清除算法。

先标记出待清除对象,再整体进行清除操作。

效率问题,容易产生大量不连续的内存碎片。

4.4.复制算法。

将内存划分为容量等大的两块,当一块用完了,就把还存活着的对象复制到另一块上,然后再把已使用过的内存空间一次性清理掉。

4.5.标记-整理算法。

让所有活着的对象都向一端移动,然后直接清理掉端过界以外的内存。

4.6.分代收集算法。

分别对新生代和老年代的内存进行回收。

5、各垃圾收集器的优缺点。

5.1.Serial收集器。

优点:简单高效,对于限定单个CPU来说,Serial收集器没有现成交互的开销,可专心做垃圾收集以获得最高的单线程收集效率。

缺点:单线程收集器,在进行垃圾收集时,必须停顿其他所有线程。

5.2.ParNew收集器。

Serial收集器的多线程版本。

5.3.Parallel Scavenge收集器。

吞吐量优先收集器:使Jvm达到一个可控的吞吐量。

吞吐量=运行用户代码时间/(运行用户代码时间+垃圾收集时间)

5.4.Serial Old收集器。

Serial收集器的老年代版本,使用标记—整理算法。

5.5.Paraller Old收集器。

使用多线程和标记—整理算法收集。

5.6.CMS收集器。

最短回收停顿,采用标记—清除算法。

优点:并发收集,低停顿。

缺点:

(a)、CPU资源敏感。

(b)、无法处理浮动垃圾,即无法处理在垃圾收集过程中产生的新垃圾。

(c)、容易产生空间碎片。

5.7.G1收集器。

并发与并行、分代收集、空间整合、可预测的停顿

6、ThreadLocal线程局部变量。

所谓线程局部变量,就是仅仅能被本线程访问,不能在线程之间共享的变量。

synchronized用于县城之间的数据共享(使变量或者代码块在某一时刻只能被一个线程访问),是一种延长访问时间来换取线程安全的策略。

ThreadLocal用于线程间的数据隔离(为每一个线程都提供了变量的副本),是一种以空间来换取线程安全的策略。

7、Java线程池ThreadExecutor。

线程池:一种多线程的处理形式,处理过程中将任务添加到队列,然后在创建线程后自动启动这些任务。

线程池线程都是后台线程,每个线程都是用默认的堆栈大小,以默认的优先级运行,并处于多线程单元中。

corePoolSize:核心线程池大小

maximumPoolSize:最大线程池大小

workQueue:阻塞任务队列

threadFactory:新建线程工厂

keepAliveTime:线程池中超过corePoolSize数目的空闲线程最大存活时间;可以allowCoreThreadTimeOut(true)使核心线程有效时间。

TimeUnit:keepAliveTime的单位。

注意:

(a)、当线程池小于corePoolSize时,新提交任务将创建一个新线程执行任务,即使此时线程池中存在空闲线程。

(b)、当线程池达到corePoolSize时,新提交的任务被放入workQueue中,等待线程池中任务调度执行。

(c)、当workQueue已满,且maximumPoolSize>corePoolSize时,新提交的任务会创建新线程执行任务。

(d)、当提交任务超过maximumPoolSize时,新提交的任务由RejectedExecutionHandler处理。

(e)、当线程池中超过corePoolSize,空闲时间达到keepAliveTime时,关闭空闲线程。

(f)、当设置allowCoreThreadTimeOut(true)时,线程池中corePoolSize线程空闲时间达到keepAliveTime也将关闭。

8、Lock关键字。

Synchronized关键字是Java语言内置关键字,Lock是一个类,通过这个类可以实现同步访问。

Synchronized不需要用户手动去释放锁,当Synchronized方法或者代码块执行完之后,系统会自动让线程释放对锁的占用;而Lock则必须要用户去手动释放锁,如果没有主动释放锁,就有可能出现死锁现象。

一般来说,使用Lock必须在try{}catch{}finally{}中执行,并且将释放锁的操作放在finally块中执行,以保证锁一定会被释放,防止死锁发生。

9、Volatile关键字。

保证不同线程对这个变量进行的操作时的可见性,所有线程都能看到共享内存的最新状态。

Java通过以下几种原子性操作完成工作内存和主内存的交互:

(a)、lock:作用于主内存,把变量标识为线程独占状态。

(b)、unlock:解除独占状态。

(c)、read:作用主内存,把一个变量的值从主内存传输到线程的工作内存。

(d)、load:作用工作内存,把read操作传过来的变量值放入工作内存的变量副本中。

(e)、use:作用工作内存,把工作内存当中的一个变量值传给执行引擎。

(f)、assign:作用工作内存,把一个从执行引擎接收到的值赋给工作内存的变量。

(g)、store:作用于工作内存的变量,把工作内存的一个变量值传送到主内存中。

(h)、write:作用于主内存的变量,把store操作传来的变量放入主内存的变量中。

Volatitle是如何保持内存的可见性?

read、load、use动作必须连续出现。

assign、store、write动作必须连续出现。

使用volatitle关键字能够保证:

每次读前必须从主内存刷新最新的值。

每次写入后必须立即同步到主内存中。

总结:volatitle关键字修饰的变量看到的随时是自己的最新值。

猜你喜欢

转载自blog.csdn.net/u012459871/article/details/82926539