ThreadLocal是什么
ThreadLocal 用于提供线程局部变量,在多线程环境可以保证各个线程里的变量独立于其它线程里的变量。也就是说 ThreadLocal 可以为每个线程创建一个【单独的变量副本】。实现了线程的数据隔离。
简单来说就是:往ThreadLocal中填充的变量属于当前线程,该变量对其他线程而言是隔离的。ThreadLocal实现原理
ThreadLocal的内部结构如下图
Love Coding,Enjoy Life
ThreadLocal 用于提供线程局部变量,在多线程环境可以保证各个线程里的变量独立于其它线程里的变量。也就是说 ThreadLocal 可以为每个线程创建一个【单独的变量副本】。实现了线程的数据隔离。
简单来说就是:往ThreadLocal中填充的变量属于当前线程,该变量对其他线程而言是隔离的。ThreadLocal的内部结构如下图
Java提供了很多SPI,允许第三方为这些接口提供实现,最常见的SPI实现有JDBC、JNDI等等,根据类加载器的双亲委派模型,加载ServiceLoader的 BootstrapClassLoader 是不能加载SPI的实现类的,因为SPI的实现类是由 AppClassLoader 加载的,而 BootstrapClassLoader 是不能委派 AppClassLoader 来加载类的,那该怎么办呢?
SPI约定为:当服务的提供者提供了服务接口的一种实现之后,在jar包的META-INF/services/目录里同时创建一个以服务接口命名的文件。该文件里就是实现该服务接口的具体实现类。而当外部程序装配这个模块的时候,就能通过该jar包META-INF/services/里的配置文件找到具体的实现类名,并装载实例化,完成模块的注入。
通过Netty的ChannelPieline 了解到了责任链模式,通过控制行为分类责任链模式有两种形式,一种是通过外部调用的方式对链的各个节点调用进行控制,从而进行链的各个节点之间的切换;另一种是链的每个节点自由控制是否继续往下传递链的进度,这种比较典型的使用方式在Netty中有所体现。
典型应用例子除了Netty 的ChannelPieline、ChannelHandler之外,还有Web的Servlet 和 Filter以声明的方式插入到Http请求响应的处理过程,用于拦截请求和响应通俗而言:责任链模式是一条链,链上有多个节点,每个节点都有各自的责任。当有输入时,第一个责任节点看自己能否处理该输入,如果可以就处理。如果不能就交由下一个责任节点处理。依次类推,直到最后一个责任节点。
在JVM中,一个类被加载到虚拟机这个过程包括有3个步骤,即加载、连接和初始化。而加载这个过程,就是由类加载器ClassLoader进行加载的,类加载器天生就负责这个职责
类加载器负责加载程序中的类(类和接口),并赋予唯一的名字予以标识
启动类加载器Bootstrap ClassLoader
最顶层的加载类,由C++实现,负责加载 %JAVA_HOME%/lib目录下的jar包和类或者被 -Xbootclasspath参数指定的路径中的所有类。
扩展类加载器Extension ClassLoader
主要负责加载目录 %JRE_HOME%/lib/ext 目录下的jar包和类,或被 java.ext.dirs 系统变量所指定的路径下的jar包。
应用类加载器App ClassLoader
面向我们用户的加载器,负责加载当前应用classpath下的所有jar包和类,它也是Java程序默认的类加载器。
虚拟机把描述类的数据从class文件加载到内存,并对数据进行校验、转换解析和初始化,最终形成可以被虚拟机直接使用的Java类型。
数组类通过JAVA虚拟机直接创建,不通过类加载器创建
JVM中类(类+接口)的加载和连接过程都是在程序运行期间第一次使用时动态加载的,而不是一次性加载所有类,这样会在类加载时稍微增加一些性能开销,但是却能为Java应用程序提供高度的灵活性,Java中天生可以动态扩展的语言特性就是依赖运行期动态加载和动态连接这个特性实现的。例如,如果编写一个使用接口的应用程序,可以等到运行时再指定其实际的实现。
RPC(Remote Procedure Call),即远程过程调用,它是一种通过网络从远程计算机程序 上请求服务,而不需要了解底层网络实现的技术。常见的RPC 框架有: 源自阿里的Dubbo, Spring 旗下的Spring Cloud,Google 出品的grpc 等等。
JDK命令行工具可以监控虚拟机性能,让程序员了解虚拟机运行状态,对出现的故障进行修复
一般当虚拟机出现问题我们查看其运行日志,异常堆栈,GC日志,线程快照(threaddump),堆转储快照(heapdump)等。在这时候中Java自带的一些状态监控命令和图形化工具就派上用场了。
jps 命令可以列出所有的 Java 进程。如果 jps 不加任何参数,可以列出 Java 程序的进程 ID 以及 Main 函数短名称
jps [options] [hostid]
options参数解释:
大多数情况下,对象在新生代Eden区中分配。当Eden区没有足够空间分配时,虚拟机发起一次Minor GC。GC后对象尝试放入Survivor空间,如果Survivor空间无法放入对象时,只能通过空间分配担保机制提前转移到老年代.
新生代中:Eden 和 Survivor 区的比例默认是 8:1:1,当然也支持参数调整 -XX:SurvivorRatio=8 (通常新生代GC时(复制算法)使用 Eden 和其中一块 Survivor。将 Eden 和 Survivor 中还存活着的对象全部复制到另一块 Survivor 上,最后清理 Eden 和使用过的那一块 Survivor,S1和S2交换使用)
Netty主要基于主从Reactors多线程模型(如下图)做了一定的修改,其中主从Reactor多线程模型有多个Reactor:MainReactor和SubReactor:MainReactor负责客户端的连接请求,并将请求转交给SubReactor。SubReactor负责相应通道的IO读写请求非IO请求(具体逻辑处理)的任务则会直接写入队列,等待worker threads进行处理
如何判断Java中一个对象应该 “存活” 还是 “死去”,这是 垃圾回收器要做的第一件事
Java 堆 中每个具体对象(不是引用)都有一个引用计数器。当一个对象被创建并初始化赋值后,该变量计数设置为1。每当有一个地方引用它时,计数器值就加1。当引用失效时,即一个对象的某个引用超过了生命周期(出作用域后)或者被设置为一个新值时,计数器值就减1。任何引用计数为0的对象可以被当作垃圾收集。当一个对象被垃圾收集时,它引用的任何对象计数减1。
可达性分析算法也叫根搜索算法,通过一系列的称为GC Roots 的对象作为起点,然后向下搜索。搜索所走过的路径称为引用链 (Reference Chain), 当一个对象到 GC Roots 没有任何引用链相连时, 即该对象不可达,也就说明此对象是 不可用的。